Antes de empezar
La API funciona sin una cuenta mediante una sesión de invitado. La API está en la dirección propia del sitio bajo /api. Defínala una vez:
API=https://dev.uliketechnology.com/api
F=board.zip
board.zip es un zip plano con sus archivos Gerber y de taladrado. Para saber qué contiene, consulte Archivos para fabricación y montaje. Los ejemplos necesitan curl y jq.
Toda solicitud a la API después de la sesión de invitado lleva Authorization: Bearer <token>. Todo error tiene la misma forma:
{ "error": { "code": "VALIDATION_FAILED", "message": "…", "details": {}, "requestId": "…" } }
Decida según code. El message es para desarrolladores.
- Sesión de invitado: el token se muestra una vez.
- Subida: envíe el zip con
PUTa la dirección que indique la API, con las cabeceras que indique. - Finalización, luego consulte hasta que el análisis termine.
- El informe: observaciones, qué comprobaciones se realizaron y cuáles no.
- La vista previa de cotización.
El flujo con curl
Lea lo que se puede pedir. Esto no necesita token:
curl -s $API/v1/capabilities | jq '.options[].id'
Abra una sesión de invitado. El token se muestra una vez y dura 30 días:
T=$(curl -s -X POST $API/v1/guest-sessions | jq -r .token)
Anuncie el archivo. La respuesta contiene uploadId, designId, uploadUrl y requiredHeaders:
J=$(curl -s -X POST $API/v1/uploads -H "authorization: Bearer $T" -H 'content-type: application/json' \
-d "{\"fileName\":\"board.zip\",\"sizeBytes\":$(stat -c %s $F),\"sha256\":\"$(sha256sum $F | cut -d' ' -f1)\",\"purpose\":\"design\"}")
Envíe el archivo a la dirección que indique la respuesta, con cada cabecera de requiredHeaders (tipo de contenido, longitud y suma de comprobación; sin ellas la subida se rechaza con 403). Después complete la subida:
curl -s -X PUT --data-binary @$F \
$(echo $J | jq -r '.requiredHeaders | to_entries[] | "-H \(.key):\(.value)"') \
"$(echo $J | jq -r .uploadUrl)"
curl -s -X POST $API/v1/uploads/$(echo $J | jq -r .uploadId)/complete -H "authorization: Bearer $T" | jq .design.status
Al principio, el estado es analysing. Lea el diseño hasta que cambie. Cuando sea ready, el informe está en la respuesta:
D=$(echo $J | jq -r .designId)
curl -s $API/v1/designs/$D -H "authorization: Bearer $T" | jq '.design.status, .report.headline, .report.counts'
El titular es no_problems_in_checks_run, problems_found o could_not_check. Lea también checksRun y checksNotRun: una comprobación que no se realizó no es una aprobación. Los demás estados son needs_mapping (defina las capas con PUT /v1/designs/{designId}/layer-mapping), needs_engineer y rejected.
Pida una vista previa de cotización. selection y destinationCountry son obligatorios; un selection vacío toma los valores por defecto:
curl -s -X POST $API/v1/quote-previews -H "authorization: Bearer $T" -H 'content-type: application/json' \
-d "{\"designId\":\"$D\",\"quantities\":{\"boardsFabricated\":10,\"boardsAssembled\":0},\"selection\":{},\"destinationCountry\":\"DE\"}" \
| jq '.mode, .reviewReasons, .totalMinor'
mode es instant (el precio se mantiene tal como se muestra) o review (un ingeniero lo confirma); reviewReasons indica por qué. totalMinor está en unidades menores de la currency de la respuesta, y está ausente cuando un ingeniero debe poner precio al trabajo. Para guardar una cotización, POST /v1/quotes acepta el mismo cuerpo.
El mismo flujo con el cliente JavaScript
El cliente @ulike/sdk envuelve estas rutas. Aún no se ha publicado como paquete; esta es su forma, para que usted pueda escribir las mismas llamadas con fetch. Nombres de métodos:
import { createClient } from '@ulike/sdk';
let token;
const api = createClient({ baseUrl: 'https://dev.uliketechnology.com/api', token: () => token });
const caps = await api.capabilities();
token = (await api.createGuestSession()).token;
const started = await api.uploadDesign({ name: 'board.zip', bytes }); // announce, PUT, complete
const view = await api.waitForDesign(started.design.id); // polls getDesign
const preview = await api.previewQuote({
designId: view.design.id,
quantities: { boardsFabricated: 10, boardsAssembled: 0 },
selection: {},
destinationCountry: 'DE',
});
Los demás métodos son createUpload, completeUpload, getDesign, setLayerMapping, validateDesign, getValidation, waitForValidation, createQuote, getQuote y reviseQuote. Los errores se lanzan como ApiClientError con un status y un code.
La verificación para un pedido
El informe que obtiene tras la subida se elabora solo con los archivos. Para verificar los archivos frente a un pedido, llame a POST /v1/designs/{designId}/validations (validateDesign) con order que contenga quantities y selection. La respuesta es un estado: running, failed o done. Mientras sea running, lea GET /v1/validations/{reportId} (getValidation) cada segundo o dos hasta que sea done.
- Suba el zip.
- Lea el informe.
- Corrija y suba como un diseño nuevo. Deténgase y pregunte a la persona cuando una corrección cambie la función, el precio o el plazo de entrega.
- Archivos limpios: ejecute la verificación para el pedido.
Una cotización o vista previa con opciones que traen otros límites (cobre más grueso, otro espesor) necesita una verificación para esa selección. Si no existe ninguna, se inicia una, y la vista previa lleva el motivo de revisión file_check_pending y un check con su reportId. El precio se muestra de inmediato, pero la cotización permanece en review hasta que esa verificación termina. Lea la verificación como se indicó arriba y después pida de nuevo la vista previa.
Errores que encontrará
| Código | Estado | Qué significa | Qué hacer |
|---|---|---|---|
DESIGN_NOT_READY |
422 | El diseño aún se está leyendo (details.status indica qué estado), o aún no tiene informe. |
Lea el diseño hasta que el estado no sea analysing, y después vuelva a pedirlo. |
VALIDATION_FAILED |
400 | La solicitud no tiene la forma esperada, o nombra una opción o un valor que el catálogo no tiene. details enumera las cuestiones o problemas. |
Corrija el campo nombrado en details y envíe de nuevo. Tome los identificadores y valores de opciones de GET /v1/capabilities. |
NOT_MANUFACTURABLE |
422 | La selección es algo que no fabricamos. details.because trae los motivos. |
Cambie la selección; no reintente la misma. Pregunte a la persona si el cambio alteraría la placa. |
ANONYMOUS_BUDGET_SPENT |
429 | La cuota diaria sin una cuenta se ha agotado. details.resetsOn es la fecha. |
Deténgase. Dígale a la persona; puede iniciar sesión o esperar hasta esa fecha. |
REVISION_CONFLICT |
409 | Una revisión nombró una base que ya no es la cabeza de la cotización. details trae ambas cabezas. |
Lea la cabeza con GET /v1/quotes/{quoteId}, vuelva a aplicar su cambio sobre ella y envíe de nuevo. |
También son posibles DESIGN_REJECTED (la subida fue rechazada; consulte details.reason), UNAUTHENTICATED por un token ausente o incorrecto (un token incorrecto se rechaza incluso en rutas públicas), y FEATURE_DISABLED para una ruta que aún no está abierta.
La cuota diaria sin una cuenta
Una sesión de invitado tiene una cuota diaria de cómputo. Las subidas y las verificaciones iniciadas cuestan más que una lectura simple, y abrir muchas sesiones de invitado desde una misma dirección de red también cuenta. Una verificación que el sitio inicia por su cuenta para una selección nueva se carga a la misma cuota. Cuando se agota, usted recibe ANONYMOUS_BUDGET_SPENT con la fecha en que se restablece. Quienes han iniciado sesión no se cuentan de este modo.
Lo que la API no puede hacer hoy: los pedidos, el pago, las claves de API y el inicio de sesión para agentes están previstos y no están disponibles. El servidor MCP previsto se describe en Qué es MCP y cómo piden los agentes.