Zanim Pan/Pani zacznie
API działa bez konta w ramach sesji gościa. API znajduje się pod własnym adresem strony, w ścieżce /api. Proszę ustawić je raz:
API=https://dev.uliketechnology.com/api
F=board.zip
board.zip to płaski plik zip z plikami Gerber i plikiem wierceń. Co się w nim znajduje, opisuje artykuł Pliki do produkcji i montażu. Przykłady potrzebują programów curl i jq.
Każde żądanie do API po sesji gościa przyjmuje nagłówek Authorization: Bearer <token>. Każdy błąd ma ten sam kształt:
{ "error": { "code": "VALIDATION_FAILED", "message": "…", "details": {}, "requestId": "…" } }
Proszę rozgałęziać według pola code. Pole message jest dla programistów.
- Sesja gościa: token jest pokazywany raz.
- Przesyłanie: proszę wysłać plik zip metodą
PUTna adres, który podaje API, z nagłówkami, które podaje API. - Zakończenie, potem odpytywanie, aż analiza będzie gotowa.
- Raport: uwagi, które sprawdzenia się wykonały, a które nie.
- Podgląd wyceny.
Proces z curl
Proszę odczytać, co można zamówić. Nie wymaga to tokena:
curl -s $API/v1/capabilities | jq '.options[].id'
Proszę otworzyć sesję gościa. Token jest pokazywany raz i trwa 30 dni:
T=$(curl -s -X POST $API/v1/guest-sessions | jq -r .token)
Proszę zapowiedzieć plik. Odpowiedź zawiera pola 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\"}")
Proszę wysłać plik na adres, który podaje odpowiedź, z każdym nagłówkiem z pola requiredHeaders (typ treści, długość i suma kontrolna; bez nich przesyłanie jest odrzucane z kodem 403). Następnie proszę zakończyć przesyłanie:
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
Status jest najpierw analysing. Proszę odczytywać projekt, aż się zmieni. Gdy będzie ready, raport znajduje się w odpowiedzi:
D=$(echo $J | jq -r .designId)
curl -s $API/v1/designs/$D -H "authorization: Bearer $T" | jq '.design.status, .report.headline, .report.counts'
Nagłówek to no_problems_in_checks_run, problems_found albo could_not_check. Proszę przeczytać też pola checksRun i checksNotRun: sprawdzenie, które się nie wykonało, nie jest zaliczeniem. Pozostałe statusy to needs_mapping (proszę ustawić warstwy wywołaniem PUT /v1/designs/{designId}/layer-mapping), needs_engineer i rejected.
Proszę poprosić o podgląd ceny. Pola selection i destinationCountry są wymagane; puste pole selection przyjmuje wartości domyślne:
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'
Pole mode to instant (cena obowiązuje tak, jak pokazano) albo review (inżynier ją potwierdza); pole reviewReasons mówi dlaczego. Pole totalMinor jest w jednostkach drobnych waluty z pola currency odpowiedzi i nie występuje, gdy inżynier musi wycenić zadanie. Aby zapisać wycenę, wywołanie POST /v1/quotes przyjmuje tę samą treść.
Ten sam proces z klientem JavaScript
Klient @ulike/sdk opakowuje te trasy. Nie jest jeszcze opublikowany jako pakiet; jest to jego kształt, aby Pan/Pani mógł/mogła zapisać te same wywołania za pomocą fetch. Nazwy metod:
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',
});
Pozostałe metody to createUpload, completeUpload, getDesign, setLayerMapping, validateDesign, getValidation, waitForValidation, createQuote, getQuote i reviseQuote. Błędy są zgłaszane jako ApiClientError z polami status i code.
Weryfikacja dla zamówienia
Raport, który Pan/Pani otrzymuje po przesłaniu, jest tworzony na samych plikach. Aby sprawdzić pliki względem zamówienia, proszę wywołać POST /v1/designs/{designId}/validations (validateDesign) z polem order zawierającym pola quantities i selection. Odpowiedź jest stanem: running, failed albo done. Gdy jest running, proszę odczytywać GET /v1/validations/{reportId} (getValidation) co sekundę albo dwie, aż będzie done.
- Przesłanie pliku zip.
- Przeczytanie raportu.
- Poprawa i przesłanie jako nowy projekt. Proszę zatrzymać się i zapytać osobę, gdy poprawka zmienia funkcję, cenę albo czas dostawy.
- Czyste pliki: proszę uruchomić sprawdzenie dla zamówienia.
Wycena albo podgląd z opcjami, które wprowadzają inne limity (grubsza miedź, inna grubość), potrzebuje sprawdzenia dla tego wyboru. Jeśli takie nie istnieje, jedno jest uruchamiane, a podgląd ma powód kontroli file_check_pending oraz pole check z jego polem reportId. Cena jest pokazywana od razu, ale wycena pozostaje w stanie review, aż to sprawdzenie się zakończy. Proszę odczytać sprawdzenie jak wyżej, a potem poprosić o podgląd ponownie.
Błędy, które Pan/Pani napotka
| Kod | Status | Co to oznacza | Co zrobić |
|---|---|---|---|
DESIGN_NOT_READY |
422 | Projekt jest jeszcze odczytywany (details.status mówi, który to stan), albo nie ma jeszcze raportu. |
Proszę odczytywać projekt, aż status nie będzie analysing, a potem zapytać ponownie. |
VALIDATION_FAILED |
400 | Żądanie nie ma oczekiwanego kształtu albo nazywa opcję lub wartość, której katalog nie ma. Pole details wymienia problemy. |
Proszę poprawić pole nazwane w polu details i wysłać ponownie. Identyfikatory opcji i wartości proszę brać z wywołania GET /v1/capabilities. |
NOT_MANUFACTURABLE |
422 | Wybór jest czymś, czego nie wykonujemy. Pole details.because zawiera powody. |
Proszę zmienić wybór; nie ponawiać tego samego. Proszę zapytać osobę, czy zmiana zmieniłaby płytkę. |
ANONYMOUS_BUDGET_SPENT |
429 | Dzienny limit bez konta jest wyczerpany. Pole details.resetsOn to data. |
Proszę się zatrzymać. Proszę powiedzieć osobie; może się zalogować albo poczekać do tej daty. |
REVISION_CONFLICT |
409 | Rewizja nazwała podstawę, która nie jest już głową wyceny. Pole details zawiera obie głowy. |
Proszę odczytać głowę wywołaniem GET /v1/quotes/{quoteId}, ponownie zastosować zmianę na niej i wysłać ponownie. |
Możliwe są też kody DESIGN_REJECTED (przesyłanie zostało odrzucone; zob. pole details.reason), UNAUTHENTICATED przy brakującym albo błędnym tokenie (błędny token jest odrzucany nawet na trasach publicznych) oraz FEATURE_DISABLED dla trasy, która nie jest jeszcze otwarta.
Dzienny limit bez konta
Sesja gościa ma dzienny limit obliczeń. Przesłanie i uruchomione sprawdzenia kosztują więcej niż zwykły odczyt, a otwieranie wielu sesji gościa z jednego adresu sieciowego też jest liczone. Sprawdzenie, które strona uruchamia sama dla nowego wyboru, jest obciążane na ten sam limit. Gdy limit się wyczerpie, otrzymuje Pan/Pani kod ANONYMOUS_BUDGET_SPENT z datą jego odnowienia. Zalogowani wywołujący nie są liczeni w ten sposób.
Czego API dziś nie potrafi: zamawianie, płatność, klucze API i logowanie dla agentów są planowane i niedostępne. Planowany serwer MCP opisuje artykuł Czym jest MCP i jak zamawiają agenci.