Avant de commencer
L'API fonctionne sans compte au moyen d'une session invité. L'API se trouve à l'adresse propre du site, sous /api. Définissez-la une fois :
API=https://dev.uliketechnology.com/api
F=board.zip
board.zip est un zip plat de vos fichiers Gerber et de perçage. Pour ce qu'il contient, voyez Fichiers pour la fabrication et l'assemblage. Les exemples ont besoin de curl et de jq.
Chaque requête à l'API après la session invité prend Authorization: Bearer <token>. Chaque erreur a la même forme :
{ "error": { "code": "VALIDATION_FAILED", "message": "…", "details": {}, "requestId": "…" } }
Décidez selon code. Le message est destiné aux développeurs.
- Session invité : le token est affiché une fois.
- Téléversement :
PUTle zip à l'adresse que l'API indique, avec les en-têtes qu'elle indique. - Terminez, puis interrogez de façon répétée jusqu'à ce que l'analyse soit terminée.
- Le rapport : observations, quelles vérifications ont été effectuées et lesquelles ne l'ont pas été.
- L'aperçu du prix.
Le flux avec curl
Lisez ce qui peut être commandé. Cela ne demande aucun token :
curl -s $API/v1/capabilities | jq '.options[].id'
Ouvrez une session invité. Le token est affiché une fois et dure 30 jours :
T=$(curl -s -X POST $API/v1/guest-sessions | jq -r .token)
Annoncez le fichier. La réponse contient uploadId, designId, uploadUrl et 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\"}")
Envoyez le fichier à l'adresse que la réponse indique, avec chaque en-tête de requiredHeaders (type de contenu, longueur et somme de contrôle ; sans eux, le téléversement est refusé avec 403). Terminez ensuite le téléversement :
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
Le statut est analysing au début. Lisez la conception jusqu'à ce qu'il change. Lorsqu'il est ready, le rapport se trouve dans la réponse :
D=$(echo $J | jq -r .designId)
curl -s $API/v1/designs/$D -H "authorization: Bearer $T" | jq '.design.status, .report.headline, .report.counts'
Le titre est no_problems_in_checks_run, problems_found ou could_not_check. Lisez aussi checksRun et checksNotRun : une vérification qui n'a pas été effectuée n'est pas une réussite. Les autres statuts sont needs_mapping (définissez les couches avec PUT /v1/designs/{designId}/layer-mapping), needs_engineer et rejected.
Demandez un aperçu de prix. selection et destinationCountry sont requis ; un selection vide prend les valeurs par défaut :
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 vaut instant (le prix reste tel qu'affiché) ou review (un ingénieur le confirme) ; reviewReasons dit pourquoi. totalMinor est exprimé en unités mineures de la currency de la réponse, et il est absent lorsqu'un ingénieur doit chiffrer le travail. Pour conserver un devis, POST /v1/quotes prend le même corps.
Le même flux avec le client JavaScript
Le client @ulike/sdk enveloppe ces routes. Il n'est pas encore publié comme paquet ; voici sa forme, afin que vous puissiez écrire les mêmes appels avec fetch. Noms de méthodes :
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',
});
Les autres méthodes sont createUpload, completeUpload, getDesign, setLayerMapping, validateDesign, getValidation, waitForValidation, createQuote, getQuote et reviseQuote. Les erreurs sont levées sous forme d'ApiClientError avec un status et un code.
La vérification pour une commande
Le rapport que vous obtenez après le téléversement est établi sur les seuls fichiers. Pour vérifier les fichiers par rapport à une commande, appelez POST /v1/designs/{designId}/validations (validateDesign) avec order contenant quantities et selection. La réponse est un état : running, failed ou done. Pendant running, lisez GET /v1/validations/{reportId} (getValidation) toutes les une à deux secondes jusqu'à ce qu'il soit done.
- Téléversez le zip.
- Lisez le rapport.
- Corrigez et téléversez comme une nouvelle conception. Arrêtez-vous et demandez à la personne lorsqu'une correction change la fonction, le prix ou le délai de livraison.
- Fichiers propres : lancez la vérification pour la commande.
Un devis ou un aperçu avec des options qui apportent d'autres limites (cuivre plus épais, autre épaisseur) a besoin d'une vérification pour cette sélection. S'il n'en existe aucune, une vérification est lancée, et l'aperçu porte le motif de revue file_check_pending et un check avec son reportId. Le prix est affiché tout de suite, mais le devis reste en review jusqu'à ce que cette vérification soit terminée. Lisez la vérification comme ci-dessus, puis demandez à nouveau l'aperçu.
Erreurs que vous rencontrerez
| Code | Statut | Ce que cela signifie | Ce qu'il faut faire |
|---|---|---|---|
DESIGN_NOT_READY |
422 | La conception est encore en cours de lecture (details.status indique dans quel état), ou n'a pas encore de rapport. |
Lisez la conception jusqu'à ce que le statut ne soit plus analysing, puis demandez à nouveau. |
VALIDATION_FAILED |
400 | La requête n'a pas la forme attendue, ou nomme une option ou une valeur que le catalogue n'a pas. details liste les points ou les problèmes. |
Corrigez le champ nommé dans details et envoyez à nouveau. Prenez les identifiants et les valeurs d'options depuis GET /v1/capabilities. |
NOT_MANUFACTURABLE |
422 | La sélection est quelque chose que nous ne fabriquons pas. details.because porte les motifs. |
Changez la sélection ; ne réessayez pas la même. Demandez à la personne si le changement modifierait la carte. |
ANONYMOUS_BUDGET_SPENT |
429 | Le quota journalier sans compte est épuisé. details.resetsOn est la date. |
Arrêtez-vous. Dites-le à la personne ; elle peut se connecter ou attendre jusqu'à cette date. |
REVISION_CONFLICT |
409 | Une révision a nommé une base qui n'est plus la tête du devis. details porte les deux têtes. |
Lisez la tête avec GET /v1/quotes/{quoteId}, réappliquez votre changement dessus, et envoyez à nouveau. |
Sont aussi possibles DESIGN_REJECTED (le téléversement a été refusé ; voyez details.reason), UNAUTHENTICATED pour un token manquant ou incorrect (un token incorrect est refusé même sur les routes publiques), et FEATURE_DISABLED pour une route qui n'est pas encore ouverte.
Le quota journalier sans compte
Une session invité a un quota journalier de calcul. Les téléversements et les vérifications lancées coûtent plus qu'une simple lecture, et l'ouverture de nombreuses sessions invité depuis une même adresse réseau est aussi comptée. Une vérification que le site lance de lui-même pour une nouvelle sélection est imputée au même quota. Lorsqu'il est épuisé, vous recevez ANONYMOUS_BUDGET_SPENT avec la date à laquelle il se réinitialise. Les appelants connectés ne sont pas comptés de cette manière.
Ce que l'API ne peut pas faire aujourd'hui : la commande, le paiement, les clés API et la connexion pour les agents sont prévus et ne sont pas disponibles. Le serveur MCP prévu est décrit dans Ce qu'est MCP et comment les agents commandent.