Développeurs
L'API BUSE
Tout ce que fait le site, un programme ou un agent peut le faire : déposer un fichier, obtenir le prix que le paiement facturera, commander et payer.
- 01Cookie de session
- 02Enveloppes JSON
- 03Pages en Markdown
01Présentation
Ce que c'est
BUSE prints parts in FDM in Agadir and delivers anywhere in Morocco, delivery included in every price.
The API is the one the website itself uses. Prices are computed on the server from the uploaded file's geometry: a client only chooses the material SKU, the finish, the quantity and whether the order is rushed, never a price, a volume or a weight.
The flow is: sign in (or sign up) → `POST /api/upload` the STL/OBJ/3MF → `POST /api/quotes/batch` to price a basket → `POST /api/addresses` → `POST /api/orders` → `POST /api/payments/checkout` for a Stripe Checkout URL. Every response is a JSON envelope `{ success, data }` or `{ success: false, error: { code, message, details } }`.
Every public HTML page also answers in Markdown with `Accept: text/markdown`; the site index for agents is /llms.txt.
02Authentification
Se connecter, puis renvoyer le cookie
Les comptes sont à e-mail et mot de passe (better-auth). La réponse de connexion pose un cookie de session ; renvoyez-le à chaque appel. Il n'y a pas encore de clés d'API.
# 1. Sign in (keeps the session cookie in cookies.txt)
curl -c cookies.txt -H 'Content-Type: application/json' \
-d '{"email":"you@example.com","password":"..."}' \
https://buse.ma/api/auth/sign-in/email
# 2. Upload the file; the key is what every pricing call takes
curl -b cookies.txt -F file=@part.stl https://buse.ma/api/upload
# 3. Price the basket as the order will charge it
curl -b cookies.txt -H 'Content-Type: application/json' \
-d '{"items":[{"fileKey":"uploads/<you>/<key>","filename":"part.stl","materialId":"mat_pla_white","quantity":2}]}' \
https://buse.ma/api/quotes/batch03Points d'accès
Tous les points d'accès
Générés depuis les validateurs que le serveur applique. Les corps de requête et les codes d'erreur sont dans le document OpenAPI.
Auth
Email + password sessions (better-auth). The session is a cookie; send it back on every call.
| Méthode | Chemin | Ce que ça fait | Auth |
|---|---|---|---|
| POST | /api/auth/sign-up/email | Create an accountEmail, password and name. A verification email is sent; the session cookie is set once verified. | Public |
| POST | /api/auth/sign-in/email | Sign inSets the `better-auth.session_token` cookie on success. Keep the cookie jar for the calls below. | Public |
| GET | /api/auth/get-session | Current sessionNull when not signed in. | Session |
| POST | /api/auth/sign-out | Sign outEnds the session. | Session |
Catalog
Materials and delivery destinations.
| Méthode | Chemin | Ce que ça fait | Auth |
|---|---|---|---|
| GET | /api/materials | Material catalogEvery in-stock colour SKU with its price per gram. Public. | Public |
| GET | /api/shipping/destinations | Delivery citiesType-ahead on the cities we deliver to; the id is what an address's `shippingDestinationId` takes. Rate limit: 60 per minute per client. | Session |
Quotes
Upload a file, price it, save a devis.
| Méthode | Chemin | Ce que ça fait | Auth |
|---|---|---|---|
| POST | /api/upload | Upload a 3D fileMultipart form with one `file` field: STL, OBJ or 3MF, up to 50 MB. The returned `key` is what every pricing call takes as `fileKey`; it lives in the caller's own namespace. Rate limit: 20 per minute per client. | Session |
| GET | /api/upload | Upload limitsAccepted extensions and the size cap. | Session |
| POST | /api/analyze | Analyse a file and price one copyGeometry (volume, bounding box, printability) plus a quote in the given SKU. A part that does not fit the 256 mm bed, is too small or is not a closed mesh is a 400 with `details.reason`. Rate limit: 20 per minute per client. | Session |
| POST | /api/quotes/calculate | Price one fileThe price of one line: SKU, finish, quantity, rush. `isRush` is refused with `reason: rushUnavailable` when the print does not fit a working day. Rate limit: 60 per minute per client. | Session |
| POST | /api/quotes/batch | Price a basketThe total an order will charge: lines, the per-order service fee, the order minimum, the plate credit and delivery (included). Always price a basket here rather than summing single lines. Rate limit: 60 per minute per client. | Session |
| POST | /api/quotes | Save a devisSaves the basket as a numbered quote (DV-YYYY-NNNN), valid for a week, re-priced from the files. Rate limit: 20 per minute per client. | Session |
| GET | /api/quotes | List my devisThe caller's saved quotes. | Session |
| GET | /api/quotes/{id} | A devisWith its lines. | Session |
| PATCH | /api/quotes/{id} | Update a devisIts status. Rate limit: 5 per minute per client. | Session |
| DELETE | /api/quotes/{id} | Delete a devisAnd its lines. | Session |
| GET | /api/quotes/{id}/pdf | The devis as PDFRe-priced from the files; `application/pdf`. | Session |
Orders
Addresses, orders, payment, invoices.
| Méthode | Chemin | Ce que ça fait | Auth |
|---|---|---|---|
| GET | /api/addresses | My addressesThe caller's delivery addresses. Rate limit: 60 per minute per client. | Session |
| POST | /api/addresses | Add an address`shippingDestinationId` must be an id from /api/shipping/destinations; an unknown city is refused with `reason: cityNotServed`. Rate limit: 20 per minute per client. | Session |
| PATCH | /api/addresses/{id} | Edit an addressThe caller's own. Rate limit: 20 per minute per client. | Session |
| DELETE | /api/addresses/{id} | Remove an addressThe caller's own. Rate limit: 20 per minute per client. | Session |
| POST | /api/orders | Place an orderPriced again from the files on the server; the response total is what Stripe will charge. `acceptTerms` must be `true`. The order is created unpaid; pay it through /api/payments/checkout. Rate limit: 20 per minute per client. | Session |
| GET | /api/orders | My ordersThe caller's orders, newest first. | Session |
| GET | /api/orders/{id}/invoice | The invoice PDFIssued when the order was paid; 404 before. | Session |
| POST | /api/payments/checkout | Pay an orderReturns a Stripe Checkout URL for the order's total, in MAD. The order turns `paid` when Stripe confirms, never from the client. Rate limit: 20 per minute per client. | Session |
Projects
Work the instant quote cannot price: a human quote.
| Méthode | Chemin | Ce que ça fait | Auth |
|---|---|---|---|
| POST | /api/requests | Submit a custom projectFor work the instant quote cannot price: a part to reproduce from photos, a batch nobody has modelled. A human answers with a quote. Rate limit: 5 per minute per client. | Session |
| GET | /api/requests | My project requestsThe caller's requests. | Session |
Cards
The 3D-printed business card generator.
| Méthode | Chemin | Ce que ça fait | Auth |
|---|---|---|---|
| POST | /api/cards | Price a business cardText and style choices only; the mesh is generated and priced on the server. Rate limit: 20 per minute per client. | Session |
Account
Profile and contact.
| Méthode | Chemin | Ce que ça fait | Auth |
|---|---|---|---|
| PATCH | /api/user/profile | Update my profileName and phone. Rate limit: 20 per minute per client. | Session |
| POST | /api/contact | Write to the workshopSends an email to the team. Public. Rate limit: 5 per minute per client. | Public |
04Erreurs
Chaque erreur est du JSON
Une validation ratée liste les champs ; une règle métier nomme une raison (rushUnavailable, cityNotServed, exceedsBuildVolume, meshNotClosed) ; une route inconnue répond la même enveloppe avec une indication.
{ "success": false,
"error": { "code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": { "errors": [{ "field": "items.0.materialId", "message": "..." }] } } }Construisez dessus
Le document est le contrat. Il manque quelque chose ? Dites-le nous.