Prima di iniziare
L'API funziona senza un account tramite una sessione ospite. L'API si trova all'indirizzo del sito sotto /api. Lo imposti una volta:
API=https://dev.uliketechnology.com/api
F=board.zip
board.zip è uno zip piatto dei Suoi file Gerber e di foratura. Per cosa contiene, veda File per fabbricazione e montaggio. Gli esempi richiedono curl e jq.
Ogni richiesta all'API dopo la sessione ospite richiede Authorization: Bearer <token>. Ogni errore ha la stessa forma:
{ "error": { "code": "VALIDATION_FAILED", "message": "…", "details": {}, "requestId": "…" } }
Scelga in base a code. Il message è per gli sviluppatori.
- Sessione ospite: il token è mostrato una volta.
- Caricamento: invii con
PUTlo zip all'indirizzo che l'API indica, con gli header che essa indica. - Completamento, poi interroghi fino a quando l'analisi è terminata.
- Il rapporto: segnalazioni, quali controlli sono stati eseguiti e quali no.
- L'anteprima del preventivo.
Il flusso con curl
Legga cosa può essere ordinato. Questo non richiede token:
curl -s $API/v1/capabilities | jq '.options[].id'
Apra una sessione ospite. Il token è mostrato una volta e dura 30 giorni:
T=$(curl -s -X POST $API/v1/guest-sessions | jq -r .token)
Annunci il file. La risposta contiene uploadId, designId, uploadUrl e 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\"}")
Invii il file all'indirizzo che la risposta indica, con ogni header in requiredHeaders (tipo di contenuto, lunghezza e checksum; senza di essi il caricamento è rifiutato con 403). Poi completi il caricamento:
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
All'inizio lo stato è analysing. Legga il progetto fino a quando cambia. Quando è ready, il rapporto è nella risposta:
D=$(echo $J | jq -r .designId)
curl -s $API/v1/designs/$D -H "authorization: Bearer $T" | jq '.design.status, .report.headline, .report.counts'
Il titolo è no_problems_in_checks_run, problems_found o could_not_check. Legga anche checksRun e checksNotRun: un controllo che non è stato eseguito non è un superamento. Gli altri stati sono needs_mapping (imposti gli strati con PUT /v1/designs/{designId}/layer-mapping), needs_engineer e rejected.
Richieda un'anteprima del prezzo. selection e destinationCountry sono obbligatori; un selection vuoto prende i valori predefiniti:
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 è instant (il prezzo resta come mostrato) o review (un ingegnere lo conferma); reviewReasons indica perché. totalMinor è in unità minori della currency della risposta ed è assente quando un ingegnere deve prezzare il lavoro. Per salvare un preventivo, POST /v1/quotes accetta lo stesso body.
Lo stesso flusso con il client JavaScript
Il client @ulike/sdk incapsula queste route. Non è ancora pubblicato come pacchetto; questa è la sua forma, in modo che Lei possa scrivere le stesse chiamate con fetch. Nomi dei metodi:
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',
});
Gli altri metodi sono createUpload, completeUpload, getDesign, setLayerMapping, validateDesign, getValidation, waitForValidation, createQuote, getQuote e reviseQuote. Gli errori sono lanciati come ApiClientError con uno status e un code.
Il controllo per un ordine
Il rapporto che Lei ottiene dopo il caricamento è realizzato sui soli file. Per controllare i file rispetto a un ordine, chiami POST /v1/designs/{designId}/validations (validateDesign) con order che contiene quantities e selection. La risposta è uno stato: running, failed o done. Mentre è running, legga GET /v1/validations/{reportId} (getValidation) ogni secondo o due fino a quando è done.
- Carichi lo zip.
- Legga il rapporto.
- Corregga e carichi come nuovo progetto. Si fermi e chieda alla persona quando una correzione cambia la funzione, il prezzo o il tempo di consegna.
- File puliti: esegua il controllo per l'ordine.
Un preventivo o un'anteprima con opzioni che comportano altri limiti (rame più spesso, un altro spessore) necessita di un controllo per quella selezione. Se non ne esiste uno, ne viene avviato uno e l'anteprima riporta il motivo di verifica file_check_pending e un check con il suo reportId. Il prezzo è mostrato subito, ma il preventivo resta in review fino a quando quel controllo è terminato. Legga il controllo come sopra, poi richieda di nuovo l'anteprima.
Errori che Lei incontrerà
| Codice | Stato | Cosa significa | Cosa fare |
|---|---|---|---|
DESIGN_NOT_READY |
422 | Il progetto è ancora in lettura (details.status indica quale stato), o non ha ancora un rapporto. |
Legga il progetto fino a quando lo stato non è analysing, poi chieda di nuovo. |
VALIDATION_FAILED |
400 | La richiesta non ha la forma attesa, o indica un'opzione o un valore che il catalogo non ha. details elenca le questioni o i problemi. |
Corregga il campo indicato in details e invii di nuovo. Prenda id e valori delle opzioni da GET /v1/capabilities. |
NOT_MANUFACTURABLE |
422 | La selezione è qualcosa che non produciamo. details.because riporta i motivi. |
Cambi la selezione; non riprovi la stessa. Chieda alla persona se la modifica altererebbe la scheda. |
ANONYMOUS_BUDGET_SPENT |
429 | La quota giornaliera senza account è esaurita. details.resetsOn è la data. |
Si fermi. Lo dica alla persona; essa può accedere o attendere fino a quella data. |
REVISION_CONFLICT |
409 | Una revisione ha indicato una base che non è più la testa del preventivo. details riporta entrambe le teste. |
Legga la testa con GET /v1/quotes/{quoteId}, riapplichi la Sua modifica su di essa e invii di nuovo. |
Sono possibili anche DESIGN_REJECTED (il caricamento è stato rifiutato; veda details.reason), UNAUTHENTICATED per un token mancante o errato (un token errato è rifiutato anche sulle route pubbliche) e FEATURE_DISABLED per una route non ancora aperta.
La quota giornaliera senza account
Una sessione ospite ha una quota giornaliera di calcolo. I caricamenti e i controlli avviati costano più di una semplice lettura e anche l'apertura di molte sessioni ospite da un solo indirizzo di rete viene conteggiata. Un controllo che il sito avvia da solo per una nuova selezione è addebitato alla stessa quota. Quando è esaurita, Lei riceve ANONYMOUS_BUDGET_SPENT con la data di reimpostazione. I chiamanti che hanno effettuato l'accesso non sono conteggiati in questo modo.
Cosa l'API non può fare oggi: l'ordine, il pagamento, le chiavi API e l'accesso per gli agenti sono previsti e non disponibili. Il server MCP previsto è descritto in Cos'è MCP e come ordinano gli agenti.