Înainte să începeți
API-ul funcționează fără cont printr-o sesiune de vizitator. API-ul este la adresa proprie a site-ului, sub /api. Setați-l o dată:
API=https://dev.uliketechnology.com/api
F=board.zip
board.zip este un fișier zip plat cu fișierele Gerber și fișierul de găurire. Ce intră în el vedeți la Fișiere pentru fabricație și asamblare. Exemplele au nevoie de curl și jq.
Fiecare cerere spre API după sesiunea de vizitator ia antetul Authorization: Bearer <token>. Fiecare eroare are aceeași formă:
{ "error": { "code": "VALIDATION_FAILED", "message": "…", "details": {}, "requestId": "…" } }
Ramificați după code. Câmpul message este pentru dezvoltatori.
- Sesiunea de vizitator: tokenul este arătat o dată.
- Încărcarea: trimiteți fișierul zip cu
PUTla adresa pe care o numește API-ul, cu anteturile pe care le numește. - Finalizarea, apoi interogarea până când analiza este gata.
- Raportul: observații, ce verificări au rulat și ce verificări nu au rulat.
- Previzualizarea ofertei.
Fluxul cu curl
Citiți ce se poate comanda. Pentru aceasta nu este nevoie de token:
curl -s $API/v1/capabilities | jq '.options[].id'
Deschideți o sesiune de vizitator. Tokenul este arătat o dată și durează 30 de zile:
T=$(curl -s -X POST $API/v1/guest-sessions | jq -r .token)
Anunțați fișierul. Răspunsul are uploadId, designId, uploadUrl și 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\"}")
Trimiteți fișierul la adresa pe care o numește răspunsul, cu fiecare antet din requiredHeaders (tipul de conținut, lungimea și suma de control; fără ele încărcarea este refuzată cu 403). Apoi finalizați încărcarea:
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
Starea este la început analysing. Citiți proiectarea până se schimbă. Când este ready, raportul este în răspuns:
D=$(echo $J | jq -r .designId)
curl -s $API/v1/designs/$D -H "authorization: Bearer $T" | jq '.design.status, .report.headline, .report.counts'
Titlul este no_problems_in_checks_run, problems_found sau could_not_check. Citiți și checksRun și checksNotRun: o verificare care nu a rulat nu este un succes. Celelalte stări sunt needs_mapping (setați straturile cu PUT /v1/designs/{designId}/layer-mapping), needs_engineer și rejected.
Cereți o previzualizare de preț. Câmpurile selection și destinationCountry sunt obligatorii; un selection gol ia valorile implicite:
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'
Câmpul mode este instant (prețul rămâne cum este arătat) sau review (un inginer îl confirmă); câmpul reviewReasons spune de ce. Câmpul totalMinor este în unități minore ale monedei currency din răspuns și lipsește când un inginer trebuie să stabilească prețul lucrării. Pentru a păstra o ofertă, POST /v1/quotes ia același corp.
Același flux cu clientul JavaScript
Clientul @ulike/sdk încapsulează aceste rute. Nu este încă publicat ca pachet; aceasta este forma lui, ca să puteți scrie aceleași apeluri cu fetch. Numele metodelor:
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',
});
Celelalte metode sunt createUpload, completeUpload, getDesign, setLayerMapping, validateDesign, getValidation, waitForValidation, createQuote, getQuote și reviseQuote. Erorile sunt aruncate ca ApiClientError cu status și code.
Verificarea pentru o comandă
Raportul primit după încărcare este făcut numai pe fișiere. Pentru a verifica fișierele față de o comandă, apelați POST /v1/designs/{designId}/validations (validateDesign) cu order care conține quantities și selection. Răspunsul este o stare: running, failed sau done. Cât timp este running, citiți GET /v1/validations/{reportId} (getValidation) la fiecare secundă sau două până când este done.
- Încărcarea fișierului zip.
- Citirea raportului.
- Corectarea și încărcarea ca proiectare nouă. Opriți-vă și întrebați persoana când o corecție schimbă funcția, prețul sau timpul de livrare.
- Fișiere curate: rulați verificarea pentru comandă.
O ofertă sau o previzualizare cu opțiuni care aduc alte limite (cupru mai gros, altă grosime) are nevoie de o verificare pentru acea selecție. Dacă nu există niciuna, una este pornită, iar previzualizarea poartă motivul de verificare file_check_pending și un câmp check cu reportId al lui. Prețul este arătat imediat, dar oferta rămâne în review până când verificarea este gata. Citiți verificarea ca mai sus, apoi cereți din nou previzualizarea.
Erorile pe care le veți întâlni
| Cod | Stare | Ce înseamnă | Ce faceți |
|---|---|---|---|
DESIGN_NOT_READY |
422 | Proiectarea este încă citită (details.status spune care stare), sau nu are încă raport. |
Citiți proiectarea până când starea nu mai este analysing, apoi cereți din nou. |
VALIDATION_FAILED |
400 | Cererea nu are forma așteptată sau numește o opțiune ori o valoare pe care catalogul nu o are. Câmpul details enumeră problemele. |
Corectați câmpul numit în details și trimiteți din nou. Luați identificatorii și valorile opțiunilor din GET /v1/capabilities. |
NOT_MANUFACTURABLE |
422 | Selecția este ceva ce nu fabricăm. Câmpul details.because poartă motivele. |
Schimbați selecția; nu reîncercați aceeași. Întrebați persoana dacă schimbarea ar modifica placa. |
ANONYMOUS_BUDGET_SPENT |
429 | Alocația zilnică fără cont este epuizată. Câmpul details.resetsOn este data. |
Opriți-vă. Spuneți persoanei; se poate autentifica sau aștepta până la acea dată. |
REVISION_CONFLICT |
409 | O revizie a numit o bază care nu mai este capul ofertei. Câmpul details poartă ambele capete. |
Citiți capul cu GET /v1/quotes/{quoteId}, reaplicați modificarea pe el și trimiteți din nou. |
Sunt posibile și codurile DESIGN_REJECTED (încărcarea a fost refuzată; vedeți details.reason), UNAUTHENTICATED pentru un token lipsă sau greșit (un token greșit este refuzat chiar și pe rutele publice) și FEATURE_DISABLED pentru o rută care nu este încă deschisă.
Alocația zilnică fără cont
O sesiune de vizitator are o alocație zilnică de calcul. Încărcările și verificările pornite costă mai mult decât o citire simplă, iar deschiderea multor sesiuni de vizitator de la aceeași adresă de rețea este și ea contorizată. O verificare pe care site-ul o pornește singur pentru o selecție nouă este taxată din aceeași alocație. Când este epuizată, primiți ANONYMOUS_BUDGET_SPENT cu data la care se resetează. Apelanții autentificați nu sunt contorizați astfel.
Ce nu poate face API-ul astăzi: comandarea, plata, cheile API și autentificarea pentru agenți sunt planificate și indisponibile. Serverul MCP planificat este descris în Ce este MCP și cum comandă agenții.