From 17b6ebd73505df9f5aef36ec5fff2ec077e33ad3 Mon Sep 17 00:00:00 2001 From: Nathan GNANKADJA Date: Fri, 12 Jun 2026 21:53:02 +0100 Subject: [PATCH] feat: [#1] type full api surface and add delivery-areas & marketplace --- .github/workflows/release.yml | 43 + README.md | 14 + examples/script.ts | 18 +- openapi.json | 1021 +------------- src/client.ts | 6 + src/index.ts | 34 + src/resources/carts.ts | 27 +- src/resources/delivery-areas.ts | 14 + src/resources/marketplace.ts | 14 + src/resources/orders.ts | 12 +- src/types/generated.ts | 2229 +++++++++++++++++++++++-------- src/types/public.ts | 187 +-- test/resources.test.ts | 39 + 13 files changed, 2003 insertions(+), 1655 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 src/resources/delivery-areas.ts create mode 100644 src/resources/marketplace.ts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..6a18f67 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,43 @@ +name: Release + +# Publishes @xedo/sdk to npm whenever a version tag (e.g. v0.1.1) is pushed. +# Auth uses npm Trusted Publishing (OIDC) — no NPM_TOKEN secret to manage. +on: + push: + tags: + - 'v*' + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write # required for OIDC trusted publishing + provenance + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + registry-url: 'https://registry.npmjs.org' + cache: npm + + # Full quality gate before anything reaches the registry. + - run: npm ci + - run: npm run generate + - run: npm run lint + - run: npm run typecheck + - run: npm test + - run: npm run build + + # Fail early if the git tag doesn't match the package.json version. + - name: Check tag matches package version + run: | + PKG_VERSION="v$(node -p "require('./package.json').version")" + if [ "$GITHUB_REF_NAME" != "$PKG_VERSION" ]; then + echo "Tag $GITHUB_REF_NAME does not match package version $PKG_VERSION" >&2 + exit 1 + fi + + # Trusted Publishing needs npm >= 11.5.1; provenance is emitted automatically. + - run: npm install -g npm@latest + - run: npm publish diff --git a/README.md b/README.md index 39462df..1bed7b4 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,13 @@ xedo.lastRateLimit; // { limit, remaining, reset } from the last call | `xedo.collections` | `list`, `listAll`, `retrieve`, `retrieveBySlug` | | `xedo.orders` | `list`, `listAll`, `retrieve`, `invoice` (PDF) | | `xedo.carts` | `list`, `listAll`, `retrieve`, `preview`, `create`, `pay`, `createAndPay` | +| `xedo.deliveryAreas` | `list` → `DeliveryArea[]` | +| `xedo.marketplace` | `retrieve` → `MarketplaceProfile` | + +Every entity is fully typed (`Product`, `Order`, `Cart`, `Collection`, …). Note +that `list()`/`listAll()` return lightweight summary rows (`OrderListItem`, +`CartListItem`) while `retrieve()` returns the full detail object (`Order`, +`Cart`). ### Pagination @@ -67,6 +74,13 @@ for await (const order of xedo.orders.listAll()) { } ``` +### Delivery areas & marketplace + +```ts +const profile = await xedo.marketplace.retrieve(); // payment config, business category… +const areas = await xedo.deliveryAreas.list(); // use area.id as delivery.deliveryAreaId +``` + ### Checkout ```ts diff --git a/examples/script.ts b/examples/script.ts index 948d503..81a3b59 100644 --- a/examples/script.ts +++ b/examples/script.ts @@ -10,20 +10,26 @@ async function main() { const ping = await xedo.ping(); console.log('marketplace', ping.marketplaceId, '(', xedo.environment, ')'); - // 2. Iterate the whole catalogue, page by page. + // 2. Inspect the merchant configuration and delivery areas. + const profile = await xedo.marketplace.retrieve(); + console.log('split payment enabled:', profile.enableSplitPayment); + const areas = await xedo.deliveryAreas.list(); + console.log('delivery areas:', areas.map((a) => `${a.name} (${a.deliveryCost})`)); + + // 3. Iterate the whole catalogue, page by page. for await (const product of xedo.products.listAll({ perPage: 100 })) { - console.log(product.publicId, product.name); + console.log(product.publicId, product.name, product.price, `stock=${product.stockQuantity}`); } - // 3. Preview a cart (stateless — no cart is created). + // 4. Preview a cart (stateless — no cart is created). const totals = await xedo.carts.preview({ items: [{ publicProductId: 'PRD-XPK39ZQA01', quantity: 2 }], - delivery: { deliveryType: 'DELIVERY', deliveryAreaId: 11 }, + delivery: { deliveryType: 'DELIVERY', deliveryAreaId: areas[0]?.id }, paymentMethod: 'external_wallet', }); - console.log('totals', totals); + console.log('total', totals.total, 'delivery', totals.deliveryCost); - // 4. Robust single-resource lookup. + // 5. Robust single-resource lookup. try { await xedo.products.retrieve('PRD-does-not-exist'); } catch (err) { diff --git a/openapi.json b/openapi.json index 55bb31b..1002a0c 100644 --- a/openapi.json +++ b/openapi.json @@ -1,1020 +1 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "Xedo Developer API", - "description": "API REST publique de Xedo. Authentification par clé Bearer xdk_…. Toutes les routes sont préfixées par `/v1`.", - "version": "1.0.0", - "contact": {} - }, - "servers": [ - { - "url": "https://systems.xedoapp.com/marketplace", - "description": "Production" - } - ], - "security": [{ "developer-api-key": [] }], - "tags": [ - { "name": "Ping", "description": "Vérification de la clé API." }, - { "name": "Products", "description": "Catalogue produits du marchand." }, - { "name": "Collections", "description": "Collections (catégories) de produits." }, - { "name": "Orders", "description": "Commandes payées." }, - { "name": "Carts", "description": "Paniers et checkout (preview, création, retry paiement)." } - ], - "paths": { - "/v1/ping": { - "get": { - "operationId": "ping", - "summary": "Vérifier la clé API", - "description": "Renvoie l'identifiant du marketplace résolu depuis la clé fournie. Utilisez cet endpoint pour valider votre clé de bout en bout.", - "tags": ["Ping"], - "responses": { - "200": { - "description": "Clé valide", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiSuccessEnvelopeDto" }, - "example": { - "success": true, - "data": { - "marketplaceId": 42, - "timestamp": "2026-05-28T10:15:00.000Z" - } - } - } - } - }, - "401": { "$ref": "#/components/responses/Unauthorized" }, - "429": { "$ref": "#/components/responses/RateLimited" } - }, - "x-codeSamples": [ - { - "lang": "curl", - "label": "curl", - "source": "curl https://systems.xedoapp.com/marketplace/v1/ping \\\n -H \"Authorization: Bearer xdk_live_xxx\"" - }, - { - "lang": "JavaScript", - "label": "Node", - "source": "const res = await fetch('https://systems.xedoapp.com/marketplace/v1/ping', {\n headers: { Authorization: 'Bearer xdk_live_xxx' }\n});\nconst json = await res.json();" - } - ] - } - }, - "/v1/products": { - "get": { - "operationId": "listProducts", - "summary": "Lister les produits", - "description": "Renvoie les produits du marchand (paginés). Par défaut, seuls les produits activés sont retournés — passez `includeDisabled=true` pour inclure également les brouillons.", - "tags": ["Products"], - "parameters": [ - { "$ref": "#/components/parameters/Page" }, - { "$ref": "#/components/parameters/PerPage" }, - { - "name": "_sort", - "in": "query", - "required": false, - "description": "Colonne de tri.", - "schema": { - "type": "string", - "enum": ["id", "name", "price", "createdAt"], - "example": "createdAt" - } - }, - { "$ref": "#/components/parameters/Order" }, - { - "name": "search", - "in": "query", - "required": false, - "description": "Recherche plein-texte sur le nom du produit (3 caractères minimum).", - "schema": { "type": "string", "example": "burger" } - }, - { - "name": "collection", - "in": "query", - "required": false, - "description": "Filtrer par slug de collection.", - "schema": { "type": "string", "example": "fast-food" } - }, - { - "name": "includeVariations", - "in": "query", - "required": false, - "description": "Inclure les variations et combinaisons (SKU) dans la réponse.", - "schema": { "type": "boolean", "default": false, "example": false } - }, - { - "name": "includeDisabled", - "in": "query", - "required": false, - "description": "Inclure les produits désactivés (brouillons). Par défaut, seuls les produits activés sont retournés.", - "schema": { "type": "boolean", "default": false, "example": false } - } - ], - "responses": { - "200": { - "description": "Liste paginée de produits", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiPaginatedEnvelopeDto" } - } - } - }, - "400": { "$ref": "#/components/responses/BadRequest" }, - "401": { "$ref": "#/components/responses/Unauthorized" }, - "429": { "$ref": "#/components/responses/RateLimited" } - }, - "x-codeSamples": [ - { - "lang": "curl", - "label": "curl", - "source": "curl 'https://systems.xedoapp.com/marketplace/v1/products?per_page=20&_sort=createdAt&_order=desc' \\\n -H \"Authorization: Bearer xdk_live_xxx\"" - }, - { - "lang": "JavaScript", - "label": "Node", - "source": "const url = new URL('https://systems.xedoapp.com/marketplace/v1/products');\nurl.searchParams.set('per_page', '20');\nurl.searchParams.set('_sort', 'createdAt');\nurl.searchParams.set('_order', 'desc');\nconst res = await fetch(url, {\n headers: { Authorization: 'Bearer xdk_live_xxx' }\n});\nconst { data, total } = await res.json();" - } - ] - } - }, - "/v1/products/{publicId}": { - "get": { - "operationId": "getProductByPublicId", - "summary": "Récupérer un produit par son identifiant public", - "description": "Renvoie un produit unique (avec variations, combinaisons et galerie). Passez `includeDisabled=true` pour résoudre également les brouillons.", - "tags": ["Products"], - "parameters": [ - { - "name": "publicId", - "in": "path", - "required": true, - "schema": { "type": "string", "example": "PRD-XPK39ZQA01" } - }, - { - "name": "includeDisabled", - "in": "query", - "required": false, - "description": "Permet de résoudre un produit désactivé (brouillon).", - "schema": { "type": "boolean", "default": false, "example": false } - } - ], - "responses": { - "200": { - "description": "Produit trouvé", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiSuccessEnvelopeDto" } - } - } - }, - "401": { "$ref": "#/components/responses/Unauthorized" }, - "404": { "$ref": "#/components/responses/ProductNotFound" }, - "429": { "$ref": "#/components/responses/RateLimited" } - } - } - }, - "/v1/products/by-slug/{slug}": { - "get": { - "operationId": "getProductBySlug", - "summary": "Récupérer un produit par son slug", - "description": "Renvoie un produit unique recherché par son slug URL-friendly. Passez `includeDisabled=true` pour résoudre également les brouillons.", - "tags": ["Products"], - "parameters": [ - { - "name": "slug", - "in": "path", - "required": true, - "schema": { "type": "string", "example": "burger-classic" } - }, - { - "name": "includeDisabled", - "in": "query", - "required": false, - "description": "Permet de résoudre un produit désactivé (brouillon).", - "schema": { "type": "boolean", "default": false, "example": false } - } - ], - "responses": { - "200": { - "description": "Produit trouvé", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiSuccessEnvelopeDto" } - } - } - }, - "401": { "$ref": "#/components/responses/Unauthorized" }, - "404": { "$ref": "#/components/responses/ProductNotFound" }, - "429": { "$ref": "#/components/responses/RateLimited" } - } - } - }, - "/v1/collections": { - "get": { - "operationId": "listCollections", - "summary": "Lister les collections", - "description": "Renvoie les collections du marchand (paginées). Supporte le tri et la recherche par nom.", - "tags": ["Collections"], - "parameters": [ - { "$ref": "#/components/parameters/Page" }, - { "$ref": "#/components/parameters/PerPage" }, - { - "name": "_sort", - "in": "query", - "required": false, - "description": "Colonne de tri.", - "schema": { - "type": "string", - "enum": ["id", "name", "createdAt"], - "example": "createdAt" - } - }, - { "$ref": "#/components/parameters/Order" }, - { - "name": "search", - "in": "query", - "required": false, - "description": "Recherche plein-texte sur le nom de la collection (3 caractères minimum).", - "schema": { "type": "string", "example": "fast-food" } - } - ], - "responses": { - "200": { - "description": "Liste paginée de collections", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiPaginatedEnvelopeDto" } - } - } - }, - "400": { "$ref": "#/components/responses/BadRequest" }, - "401": { "$ref": "#/components/responses/Unauthorized" }, - "429": { "$ref": "#/components/responses/RateLimited" } - } - } - }, - "/v1/collections/{publicId}": { - "get": { - "operationId": "getCollectionByPublicId", - "summary": "Récupérer une collection par son identifiant public", - "tags": ["Collections"], - "parameters": [ - { - "name": "publicId", - "in": "path", - "required": true, - "schema": { "type": "string", "example": "COL-9023748120" } - } - ], - "responses": { - "200": { - "description": "Collection trouvée", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiSuccessEnvelopeDto" } - } - } - }, - "401": { "$ref": "#/components/responses/Unauthorized" }, - "404": { "$ref": "#/components/responses/NotFound" }, - "429": { "$ref": "#/components/responses/RateLimited" } - } - } - }, - "/v1/collections/by-slug/{slug}": { - "get": { - "operationId": "getCollectionBySlug", - "summary": "Récupérer une collection par son slug", - "tags": ["Collections"], - "parameters": [ - { - "name": "slug", - "in": "path", - "required": true, - "schema": { "type": "string", "example": "fast-food" } - } - ], - "responses": { - "200": { - "description": "Collection trouvée", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiSuccessEnvelopeDto" } - } - } - }, - "401": { "$ref": "#/components/responses/Unauthorized" }, - "404": { "$ref": "#/components/responses/NotFound" }, - "429": { "$ref": "#/components/responses/RateLimited" } - } - } - }, - "/v1/orders": { - "get": { - "operationId": "listOrders", - "summary": "Lister les commandes", - "description": "Renvoie les commandes du marchand (paniers payés) paginées. Supporte la recherche sur le `publicId` de commande, la référence de paiement et les données client.", - "tags": ["Orders"], - "parameters": [ - { "$ref": "#/components/parameters/Page" }, - { "$ref": "#/components/parameters/PerPage" }, - { - "name": "_sort", - "in": "query", - "required": false, - "description": "Colonne de tri.", - "schema": { - "type": "string", - "enum": ["id", "createdAt", "amount"], - "example": "createdAt" - } - }, - { "$ref": "#/components/parameters/Order" }, - { - "name": "search", - "in": "query", - "required": false, - "description": "Recherche plein-texte sur le `publicId` de commande, la référence de paiement ou les infos client.", - "schema": { "type": "string", "example": "ORD-XPK" } - } - ], - "responses": { - "200": { - "description": "Liste paginée de commandes", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiPaginatedEnvelopeDto" } - } - } - }, - "400": { "$ref": "#/components/responses/BadRequest" }, - "401": { "$ref": "#/components/responses/Unauthorized" }, - "429": { "$ref": "#/components/responses/RateLimited" } - } - } - }, - "/v1/orders/{publicId}": { - "get": { - "operationId": "getOrderByPublicId", - "summary": "Récupérer une commande par son identifiant public", - "description": "Renvoie le détail d'une commande (items, totaux, paiement, livraison).", - "tags": ["Orders"], - "parameters": [ - { - "name": "publicId", - "in": "path", - "required": true, - "schema": { "type": "string", "example": "ORD-XPK39ZQA01" } - } - ], - "responses": { - "200": { - "description": "Commande trouvée", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiSuccessEnvelopeDto" } - } - } - }, - "401": { "$ref": "#/components/responses/Unauthorized" }, - "404": { "$ref": "#/components/responses/NotFound" }, - "429": { "$ref": "#/components/responses/RateLimited" } - } - } - }, - "/v1/orders/{publicId}/invoice": { - "get": { - "operationId": "getOrderInvoice", - "summary": "Télécharger la facture (PDF)", - "description": "Renvoie la facture de la commande au format PDF (`application/pdf`). Renvoie 404 si aucune facture n'a encore été générée.", - "tags": ["Orders"], - "parameters": [ - { - "name": "publicId", - "in": "path", - "required": true, - "schema": { "type": "string", "example": "ORD-XPK39ZQA01" } - } - ], - "responses": { - "200": { - "description": "Flux PDF de la facture", - "content": { - "application/pdf": { - "schema": { "type": "string", "format": "binary" } - } - } - }, - "401": { "$ref": "#/components/responses/Unauthorized" }, - "404": { "$ref": "#/components/responses/NotFound" }, - "429": { "$ref": "#/components/responses/RateLimited" } - } - } - }, - "/v1/carts": { - "get": { - "operationId": "listCarts", - "summary": "Lister les paniers", - "description": "Renvoie les paniers du marchand (paginés). Les paniers `DRAFT` sont réservés à un usage interne et ne sont jamais exposés.", - "tags": ["Carts"], - "parameters": [ - { "$ref": "#/components/parameters/Page" }, - { "$ref": "#/components/parameters/PerPage" }, - { - "name": "_sort", - "in": "query", - "required": false, - "description": "Colonne de tri.", - "schema": { - "type": "string", - "enum": ["id", "createdAt"], - "example": "createdAt" - } - }, - { "$ref": "#/components/parameters/Order" }, - { - "name": "search", - "in": "query", - "required": false, - "description": "Recherche plein-texte sur le `publicId` de panier ou les infos client.", - "schema": { "type": "string", "example": "CART-XPK" } - } - ], - "responses": { - "200": { - "description": "Liste paginée de paniers", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiPaginatedEnvelopeDto" } - } - } - }, - "400": { "$ref": "#/components/responses/BadRequest" }, - "401": { "$ref": "#/components/responses/Unauthorized" }, - "429": { "$ref": "#/components/responses/RateLimited" } - } - }, - "post": { - "operationId": "createCart", - "summary": "Créer un panier et initier le paiement", - "description": "Crée un panier en `PENDING_PAYMENT` avec le client / les items / la livraison fournis, génère une ligne de paiement et demande une URL de checkout au provider de paiement. Si l'appel provider échoue, le panier est conservé et un `502 PAYMENT_INIT_FAILED` est retourné — relancez via `POST /v1/carts/{publicId}/pay`.", - "tags": ["Carts"], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiCheckoutCreateDto" } - } - } - }, - "responses": { - "201": { - "description": "Panier créé, URL de checkout dans `data.checkoutUrl`", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiSuccessEnvelopeDto" } - } - } - }, - "400": { "$ref": "#/components/responses/BadRequest" }, - "401": { "$ref": "#/components/responses/Unauthorized" }, - "404": { "$ref": "#/components/responses/CheckoutNotFound" }, - "422": { "$ref": "#/components/responses/InsufficientStock" }, - "429": { "$ref": "#/components/responses/RateLimited" }, - "502": { "$ref": "#/components/responses/PaymentInitFailed" } - }, - "x-codeSamples": [ - { - "lang": "curl", - "label": "curl", - "source": "curl -X POST https://systems.xedoapp.com/marketplace/v1/carts \\\n -H \"Authorization: Bearer xdk_live_xxx\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"customer\": { \"firstName\": \"Jean\", \"lastName\": \"Kouassi\", \"email\": \"jean@example.com\", \"phone\": \"+225 07 12 34 56 78\" },\n \"items\": [{ \"publicProductId\": \"PRD-XPK39ZQA01\", \"quantity\": 2 }],\n \"delivery\": { \"deliveryType\": \"DELIVERY\", \"deliveryAreaId\": 11 },\n \"paymentMethod\": \"external_wallet\",\n \"returnUrl\": \"https://my-shop.com/after-checkout\"\n }'" - }, - { - "lang": "JavaScript", - "label": "Node", - "source": "const res = await fetch('https://systems.xedoapp.com/marketplace/v1/carts', {\n method: 'POST',\n headers: {\n Authorization: 'Bearer xdk_live_xxx',\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n customer: { firstName: 'Jean', lastName: 'Kouassi', email: 'jean@example.com', phone: '+225 07 12 34 56 78' },\n items: [{ publicProductId: 'PRD-XPK39ZQA01', quantity: 2 }],\n delivery: { deliveryType: 'DELIVERY', deliveryAreaId: 11 },\n paymentMethod: 'external_wallet',\n returnUrl: 'https://my-shop.com/after-checkout'\n })\n});\nconst { data } = await res.json();\nwindow.location.href = data.checkoutUrl;" - } - ] - } - }, - "/v1/carts/{publicId}": { - "get": { - "operationId": "getCartByPublicId", - "summary": "Récupérer un panier par son identifiant public", - "description": "Renvoie le détail d'un panier (items, totaux, livraison).", - "tags": ["Carts"], - "parameters": [ - { - "name": "publicId", - "in": "path", - "required": true, - "schema": { "type": "string", "example": "CART-XPK39ZQA01" } - } - ], - "responses": { - "200": { - "description": "Panier trouvé", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiSuccessEnvelopeDto" } - } - } - }, - "401": { "$ref": "#/components/responses/Unauthorized" }, - "404": { "$ref": "#/components/responses/CartNotFound" }, - "429": { "$ref": "#/components/responses/RateLimited" } - } - } - }, - "/v1/carts/preview": { - "post": { - "operationId": "previewCart", - "summary": "Calculer les totaux d'un panier sans le persister", - "description": "Prévisualisation sans état. Valide les items, la zone de livraison et la configuration split, puis renvoie les totaux finaux. Aucun panier n'est créé.", - "tags": ["Carts"], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiCheckoutPreviewDto" } - } - } - }, - "responses": { - "200": { - "description": "Totaux calculés", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiSuccessEnvelopeDto" } - } - } - }, - "400": { "$ref": "#/components/responses/BadRequest" }, - "401": { "$ref": "#/components/responses/Unauthorized" }, - "404": { "$ref": "#/components/responses/CheckoutNotFound" }, - "422": { "$ref": "#/components/responses/InsufficientStock" }, - "429": { "$ref": "#/components/responses/RateLimited" } - }, - "x-codeSamples": [ - { - "lang": "curl", - "label": "curl", - "source": "curl -X POST https://systems.xedoapp.com/marketplace/v1/carts/preview \\\n -H \"Authorization: Bearer xdk_live_xxx\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"items\": [{ \"publicProductId\": \"PRD-XPK39ZQA01\", \"quantity\": 2 }],\n \"delivery\": { \"deliveryType\": \"DELIVERY\", \"deliveryAreaId\": 11 },\n \"paymentMethod\": \"external_wallet\"\n }'" - }, - { - "lang": "JavaScript", - "label": "Node", - "source": "const res = await fetch('https://systems.xedoapp.com/marketplace/v1/carts/preview', {\n method: 'POST',\n headers: {\n Authorization: 'Bearer xdk_live_xxx',\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n items: [{ publicProductId: 'PRD-XPK39ZQA01', quantity: 2 }],\n delivery: { deliveryType: 'DELIVERY', deliveryAreaId: 11 },\n paymentMethod: 'external_wallet'\n })\n});\nconst { data } = await res.json();" - } - ] - } - }, - "/v1/carts/{publicId}/pay": { - "post": { - "operationId": "retryCartPayment", - "summary": "Relancer l'initialisation du paiement d'un panier existant", - "description": "À utiliser uniquement lorsque l'appel précédent à `POST /v1/carts` a renvoyé `502 PAYMENT_INIT_FAILED` — c'est-à-dire que le panier est en `PENDING_PAYMENT` avec une ligne de paiement en attente. Re-sollicite le provider de paiement avec la même référence.", - "tags": ["Carts"], - "parameters": [ - { - "name": "publicId", - "in": "path", - "required": true, - "schema": { "type": "string", "example": "CART-XPK39ZQA01" } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiCheckoutRetryPayDto" } - } - } - }, - "responses": { - "200": { - "description": "Nouvelle URL de checkout dans `data.checkoutUrl`", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiSuccessEnvelopeDto" } - } - } - }, - "401": { "$ref": "#/components/responses/Unauthorized" }, - "404": { "$ref": "#/components/responses/CartNotFound" }, - "409": { "$ref": "#/components/responses/CartNotRetryable" }, - "429": { "$ref": "#/components/responses/RateLimited" }, - "502": { "$ref": "#/components/responses/PaymentInitFailed" } - } - } - } - }, - "components": { - "securitySchemes": { - "developer-api-key": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "xdk_…", - "description": "Clé API Developer émise depuis le tableau de bord marchand. Format : `xdk_live_…` ou `xdk_test_…`." - } - }, - "parameters": { - "Page": { - "name": "page", - "in": "query", - "required": false, - "description": "Numéro de page (≥ 1).", - "schema": { "type": "integer", "minimum": 1, "default": 1, "example": 1 } - }, - "PerPage": { - "name": "per_page", - "in": "query", - "required": false, - "description": "Taille de page (bornée par la config plateforme, ~100 max).", - "schema": { "type": "integer", "minimum": 1, "default": 10, "example": 10 } - }, - "Order": { - "name": "_order", - "in": "query", - "required": false, - "description": "Sens de tri.", - "schema": { - "type": "string", - "enum": ["asc", "desc"], - "default": "desc", - "example": "desc" - } - } - }, - "responses": { - "Unauthorized": { - "description": "Clé API manquante ou invalide", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiErrorEnvelopeDto" }, - "examples": { - "missing": { - "summary": "Header Authorization absent", - "value": { - "success": false, - "code": "MISSING_DEVELOPER_API_KEY", - "message": "Aucune clé API n'a été fournie" - } - }, - "invalid": { - "summary": "Clé inconnue ou désactivée", - "value": { - "success": false, - "code": "INVALID_DEVELOPER_API_KEY", - "message": "Clé API invalide" - } - } - } - } - } - }, - "BadRequest": { - "description": "Requête invalide (validation du body ou de la query)", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiErrorEnvelopeDto" }, - "example": { - "success": false, - "code": "BAD_REQUEST", - "message": "La requête est invalide", - "errors": { - "items": ["doit contenir au moins 1 élément"] - } - } - } - } - }, - "NotFound": { - "description": "Ressource introuvable", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiErrorEnvelopeDto" }, - "example": { - "success": false, - "code": "NOT_FOUND", - "message": "Ressource introuvable" - } - } - } - }, - "ProductNotFound": { - "description": "Produit introuvable", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiErrorEnvelopeDto" }, - "example": { - "success": false, - "code": "PRODUCT_NOT_FOUND", - "message": "Le produit n'a pas été trouvé" - } - } - } - }, - "CartNotFound": { - "description": "Panier introuvable", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiErrorEnvelopeDto" }, - "example": { - "success": false, - "code": "CART_NOT_FOUND", - "message": "Le panier n'a pas été trouvé" - } - } - } - }, - "CartNotRetryable": { - "description": "Le panier n'est plus dans un état autorisant un retry", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiErrorEnvelopeDto" }, - "example": { - "success": false, - "code": "CART_NOT_RETRYABLE", - "message": "Ce panier n'est plus en attente de paiement" - } - } - } - }, - "CheckoutNotFound": { - "description": "Une dépendance du checkout est introuvable (produit, combinaison ou zone de livraison)", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiErrorEnvelopeDto" }, - "examples": { - "product": { - "summary": "Produit inconnu", - "value": { - "success": false, - "code": "PRODUCT_NOT_FOUND", - "message": "Le produit n'a pas été trouvé" - } - }, - "combination": { - "summary": "Combinaison inconnue", - "value": { - "success": false, - "code": "COMBINATION_NOT_FOUND", - "message": "La combinaison n'a pas été trouvée" - } - }, - "deliveryArea": { - "summary": "Zone de livraison inconnue", - "value": { - "success": false, - "code": "DELIVERY_AREA_NOT_FOUND", - "message": "La zone de livraison n'a pas été trouvée" - } - } - } - } - } - }, - "InsufficientStock": { - "description": "Stock insuffisant pour un ou plusieurs items", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiErrorEnvelopeDto" }, - "example": { - "success": false, - "code": "INSUFFICIENT_STOCK", - "message": "Le stock est insuffisant", - "errors": { - "PRD-XPK39ZQA01": ["stock disponible : 1, demandé : 2"] - } - } - } - } - }, - "RateLimited": { - "description": "Limite de débit dépassée. Consultez le header `Retry-After` (secondes).", - "headers": { - "Retry-After": { - "description": "Nombre de secondes à attendre avant de réessayer.", - "schema": { "type": "integer", "example": 24 } - }, - "X-RateLimit-Limit": { - "description": "Limite de la fenêtre courante.", - "schema": { "type": "integer", "example": 600 } - }, - "X-RateLimit-Remaining": { - "description": "Requêtes restantes dans la fenêtre.", - "schema": { "type": "integer", "example": 0 } - }, - "X-RateLimit-Reset": { - "description": "Timestamp Unix de réinitialisation de la fenêtre.", - "schema": { "type": "integer", "example": 1716639600 } - } - }, - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiErrorEnvelopeDto" }, - "example": { - "success": false, - "code": "RATE_LIMITED", - "message": "Trop de requêtes, veuillez patienter" - } - } - } - }, - "PaymentInitFailed": { - "description": "Le provider de paiement n'a pas pu être joint. Le panier est conservé — relancez via `POST /v1/carts/{publicId}/pay`.", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/DevApiErrorEnvelopeDto" }, - "example": { - "success": false, - "code": "PAYMENT_INIT_FAILED", - "message": "L'initialisation du paiement a échoué, réessayez via /pay", - "data": { - "cartPublicId": "CART-XPK39ZQA01" - } - } - } - } - } - }, - "schemas": { - "DevApiSuccessEnvelopeDto": { - "type": "object", - "description": "Enveloppe de réponse standard pour une ressource unique.", - "properties": { - "success": { "type": "boolean", "example": true }, - "data": { "type": "object", "description": "Charge utile de la réponse." } - }, - "required": ["success", "data"] - }, - "DevApiPaginatedEnvelopeDto": { - "type": "object", - "description": "Enveloppe de réponse standard pour une collection paginée. Le header `Content-Range` accompagne toujours cette réponse.", - "properties": { - "success": { "type": "boolean", "example": true }, - "data": { - "type": "array", - "items": { "type": "object" }, - "description": "Tableau d'éléments pour la page courante." - }, - "total": { - "type": "integer", - "example": 42, - "description": "Nombre total de lignes correspondant à la requête." - }, - "start": { - "type": "integer", - "example": 1, - "description": "Index (1-based) de la première ligne renvoyée." - }, - "end": { - "type": "integer", - "example": 10, - "description": "Index (1-based) de la dernière ligne renvoyée." - } - }, - "required": ["success", "data", "total", "start", "end"] - }, - "DevApiErrorEnvelopeDto": { - "type": "object", - "description": "Enveloppe d'erreur standard. Le champ `errors` (optionnel) détaille les violations par champ pour les erreurs de validation.", - "properties": { - "success": { "type": "boolean", "example": false }, - "code": { - "type": "string", - "description": "Code d'erreur machine-readable. Voir la page Ressources › Erreurs pour la liste complète.", - "example": "PRODUCT_NOT_FOUND" - }, - "message": { - "type": "string", - "description": "Message lisible par un humain (français).", - "example": "Le produit n'a pas été trouvé" - }, - "errors": { - "type": "object", - "description": "Détail des violations par champ (uniquement pour les erreurs de validation).", - "additionalProperties": { - "type": "array", - "items": { "type": "string" } - } - }, - "data": { - "type": "object", - "description": "Contexte additionnel optionnel (ex. `cartPublicId` sur `PAYMENT_INIT_FAILED`)." - } - }, - "required": ["success", "code", "message"] - }, - "DevApiCheckoutItemDto": { - "type": "object", - "properties": { - "publicProductId": { "type": "string", "example": "PRD-XPK39ZQA01" }, - "quantity": { "type": "integer", "example": 2, "minimum": 1 }, - "combinationPublicId": { - "type": "string", - "example": "COMB-ABC123", - "description": "Identifiant public de la combinaison (SKU) si le produit a des variations." - } - }, - "required": ["publicProductId", "quantity"] - }, - "DevApiCheckoutDeliveryDto": { - "type": "object", - "properties": { - "deliveryType": { - "type": "string", - "enum": ["DELIVERY", "PICKUP"], - "example": "DELIVERY" - }, - "deliveryAreaId": { - "type": "integer", - "example": 11, - "description": "Requis lorsque `deliveryType = DELIVERY`." - } - }, - "required": ["deliveryType"] - }, - "DevApiCheckoutCustomerDto": { - "type": "object", - "properties": { - "firstName": { "type": "string", "example": "Jean" }, - "lastName": { "type": "string", "example": "Kouassi" }, - "email": { "type": "string", "format": "email", "example": "jean@example.com" }, - "phone": { "type": "string", "example": "+225 07 12 34 56 78" } - }, - "required": ["firstName", "lastName", "email", "phone"] - }, - "DevApiCheckoutPreviewDto": { - "type": "object", - "properties": { - "items": { - "type": "array", - "items": { "$ref": "#/components/schemas/DevApiCheckoutItemDto" } - }, - "delivery": { "$ref": "#/components/schemas/DevApiCheckoutDeliveryDto" }, - "paymentMethod": { - "type": "string", - "enum": ["external_wallet", "split_payment"], - "example": "external_wallet", - "description": "Modes de paiement actuellement exposés par la Developer API." - } - }, - "required": ["items", "delivery", "paymentMethod"] - }, - "DevApiCheckoutCreateDto": { - "type": "object", - "properties": { - "customer": { "$ref": "#/components/schemas/DevApiCheckoutCustomerDto" }, - "items": { - "type": "array", - "items": { "$ref": "#/components/schemas/DevApiCheckoutItemDto" } - }, - "delivery": { "$ref": "#/components/schemas/DevApiCheckoutDeliveryDto" }, - "paymentMethod": { - "type": "string", - "enum": ["external_wallet", "split_payment"], - "example": "external_wallet" - }, - "returnUrl": { - "type": "string", - "format": "uri", - "example": "https://my-shop.com/after-checkout", - "description": "URL HTTPS vers laquelle le client est redirigé après le checkout. Doit obligatoirement être en HTTPS." - }, - "additionalDetails": { - "type": "string", - "example": "Appeler 30 min avant" - }, - "meta": { - "type": "object", - "description": "Charge JSON libre renvoyée telle quelle dans toutes les réponses panier / commande. Utilisez-la pour rattacher vos propres identifiants (ex. `internalOrderId`).", - "example": { - "internalOrderId": "ORD-12345", - "source": "mobile-app" - } - } - }, - "required": [ - "customer", - "items", - "delivery", - "paymentMethod", - "returnUrl" - ] - }, - "DevApiCheckoutRetryPayDto": { - "type": "object", - "properties": { - "returnUrl": { - "type": "string", - "format": "uri", - "example": "https://my-shop.com/after-checkout" - } - }, - "required": ["returnUrl"] - } - } - } -} +{"openapi":"3.0.0","paths":{"/v1/ping":{"get":{"description":"Returns the marketplace id resolved from the provided API key. Use it to verify that your key works end-to-end.","operationId":"DevApiPingController_ping","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DevApiSuccessEnvelopeDto"},{"properties":{"data":{"$ref":"#/components/schemas/PingPayload"}}}]}}}},"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"Authenticated ping","tags":["Ping"]}},"/v1/products":{"get":{"description":"Returns the marchant's products (paginated). By default only enabled products are returned — set `includeDisabled=true` to also return drafts.","operationId":"ProductsDevApiController_list","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"example":1,"type":"number"}},{"name":"per_page","required":false,"in":"query","schema":{"minimum":1,"example":10,"type":"number"}},{"name":"_sort","required":false,"in":"query","description":"Column to sort by.","schema":{"example":"createdAt","type":"string","enum":["id","name","price","createdAt"]}},{"name":"_order","required":false,"in":"query","description":"Sort direction","schema":{"example":"desc","type":"string","enum":["asc","desc"]}},{"name":"search","required":false,"in":"query","description":"Full-text search on product name (min 3 characters).","schema":{"example":"burger","type":"string"}},{"name":"collection","required":false,"in":"query","description":"Filter by collection slug.","schema":{"example":"fast-food","type":"string"}},{"name":"includeVariations","required":false,"in":"query","description":"Include variations and combinations (SKUs) in the response.","schema":{"default":false,"example":false,"type":"boolean"}},{"name":"includeDisabled","required":false,"in":"query","description":"Include disabled (draft) products. Defaults to false — only enabled products are returned.","schema":{"default":false,"example":false,"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DevApiPaginatedEnvelopeDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DevApiProductDto"}}}}]}}}},"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"List products","tags":["Products"]}},"/v1/products/{publicId}":{"get":{"description":"Returns a single product (with variations, combinations and gallery). Set `includeDisabled=true` to also resolve drafts.","operationId":"ProductsDevApiController_getByPublicId","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}},{"name":"publicId","required":true,"in":"path","schema":{"example":"6528412905","type":"string"}},{"name":"includeDisabled","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DevApiSuccessEnvelopeDto"},{"properties":{"data":{"$ref":"#/components/schemas/DevApiProductDto"}}}]}}}},"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"404":{"description":"The requested resource does not exist (`code: NOT_FOUND`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"Get a product by its public id","tags":["Products"]}},"/v1/products/by-slug/{slug}":{"get":{"description":"Returns a single product looked up by its URL-friendly slug. Set `includeDisabled=true` to also resolve drafts.","operationId":"ProductsDevApiController_getBySlug","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}},{"name":"slug","required":true,"in":"path","schema":{"example":"burger","type":"string"}},{"name":"includeDisabled","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DevApiSuccessEnvelopeDto"},{"properties":{"data":{"$ref":"#/components/schemas/DevApiProductDto"}}}]}}}},"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"404":{"description":"The requested resource does not exist (`code: NOT_FOUND`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"Get a product by slug","tags":["Products"]}},"/v1/collections":{"get":{"description":"Returns the marchant's collections (paginated). Supports sorting and search by name.","operationId":"CollectionsDevApiController_list","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"example":1,"type":"number"}},{"name":"per_page","required":false,"in":"query","schema":{"minimum":1,"example":10,"type":"number"}},{"name":"_sort","required":false,"in":"query","description":"Column to sort by.","schema":{"example":"createdAt","type":"string","enum":["id","name","createdAt"]}},{"name":"_order","required":false,"in":"query","description":"Sort direction","schema":{"example":"desc","type":"string","enum":["asc","desc"]}},{"name":"search","required":false,"in":"query","description":"Full-text search on collection name (min 3 characters).","schema":{"example":"burger","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DevApiPaginatedEnvelopeDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DevApiCollectionDto"}}}}]}}}},"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"List collections","tags":["Collections"]}},"/v1/collections/{publicId}":{"get":{"operationId":"CollectionsDevApiController_getByPublicId","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}},{"name":"publicId","required":true,"in":"path","schema":{"example":"9023748120","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DevApiSuccessEnvelopeDto"},{"properties":{"data":{"$ref":"#/components/schemas/DevApiCollectionDto"}}}]}}}},"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"404":{"description":"The requested resource does not exist (`code: NOT_FOUND`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"Get a collection by its public id","tags":["Collections"]}},"/v1/collections/by-slug/{slug}":{"get":{"operationId":"CollectionsDevApiController_getBySlug","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}},{"name":"slug","required":true,"in":"path","schema":{"example":"fast-food","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DevApiSuccessEnvelopeDto"},{"properties":{"data":{"$ref":"#/components/schemas/DevApiCollectionDto"}}}]}}}},"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"404":{"description":"The requested resource does not exist (`code: NOT_FOUND`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"Get a collection by slug","tags":["Collections"]}},"/v1/orders":{"get":{"description":"Returns the merchant's orders (paid carts) paginated. Supports search on order publicId, payment reference and customer data.","operationId":"OrdersDevApiController_list","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"example":1,"type":"number"}},{"name":"per_page","required":false,"in":"query","schema":{"minimum":1,"example":10,"type":"number"}},{"name":"_sort","required":false,"in":"query","description":"Column to sort by.","schema":{"example":"createdAt","type":"string","enum":["id","createdAt","amount"]}},{"name":"_order","required":false,"in":"query","description":"Sort direction","schema":{"example":"desc","type":"string","enum":["asc","desc"]}},{"name":"search","required":false,"in":"query","description":"Full-text search on order publicId, payment reference or customer info.","schema":{"example":"CMD-2024","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DevApiPaginatedEnvelopeDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DevApiOrderListItemDto"}}}}]}}}},"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"List orders","tags":["Orders"]}},"/v1/orders/{publicId}":{"get":{"description":"Returns the order detail (items, totals, payment, delivery).","operationId":"OrdersDevApiController_getByPublicId","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}},{"name":"publicId","required":true,"in":"path","schema":{"example":"ORD-XPK39ZQA01","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DevApiSuccessEnvelopeDto"},{"properties":{"data":{"$ref":"#/components/schemas/DevApiOrderDetailDto"}}}]}}}},"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"404":{"description":"The requested resource does not exist (`code: NOT_FOUND`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"Get an order by its public id","tags":["Orders"]}},"/v1/orders/{publicId}/invoice":{"get":{"description":"Streams the order invoice as a PDF. Returns 404 if no invoice has been generated yet.","operationId":"OrdersDevApiController_getInvoice","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}},{"name":"publicId","required":true,"in":"path","schema":{"example":"ORD-XPK39ZQA01","type":"string"}}],"responses":{"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"404":{"description":"The requested resource does not exist (`code: NOT_FOUND`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"Download the order invoice (PDF)","tags":["Orders"]}},"/v1/carts":{"get":{"description":"Returns the merchant's carts (paginated). DRAFT carts are reserved for internal usage and are never exposed.","operationId":"CartsDevApiController_list","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"example":1,"type":"number"}},{"name":"per_page","required":false,"in":"query","schema":{"minimum":1,"example":10,"type":"number"}},{"name":"_sort","required":false,"in":"query","description":"Column to sort by.","schema":{"example":"createdAt","type":"string","enum":["id","createdAt"]}},{"name":"_order","required":false,"in":"query","description":"Sort direction","schema":{"example":"desc","type":"string","enum":["asc","desc"]}},{"name":"search","required":false,"in":"query","description":"Full-text search on cart publicId or customer info.","schema":{"example":"CMD-2024","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DevApiPaginatedEnvelopeDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DevApiCartListItemDto"}}}}]}}}},"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"List carts","tags":["Carts"]},"post":{"description":"Creates a PENDING_PAYMENT cart with the given customer/items/delivery, generates a payment row, and asks the payment provider for a checkout URL. If the provider call fails, the cart is kept and a 502 PAYMENT_INIT_FAILED is returned — retry via POST /v1/carts/{publicId}/pay.","operationId":"CheckoutDevApiController_create","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiCheckoutCreateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DevApiSuccessEnvelopeDto"},{"properties":{"data":{"$ref":"#/components/schemas/DevApiCheckoutCreateResponseDto"}}}]}}}},"400":{"description":"Invalid request — malformed parameters or body (`code: BAD_REQUEST`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"404":{"description":"The requested resource does not exist (`code: NOT_FOUND`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"422":{"description":"The request is well-formed but cannot be processed (`code: UNPROCESSABLE_ENTITY`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"502":{"description":"The payment provider could not be reached (`code: PAYMENT_INIT_FAILED`). `data.cartPublicId` carries the created cart so the payment can be retried.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"Create a cart and initiate its payment in one call","tags":["Carts"]}},"/v1/carts/{publicId}":{"get":{"description":"Returns the cart detail (items, totals, delivery info).","operationId":"CartsDevApiController_getByPublicId","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}},{"name":"publicId","required":true,"in":"path","schema":{"example":"CART-XPK39ZQA01","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DevApiSuccessEnvelopeDto"},{"properties":{"data":{"$ref":"#/components/schemas/DevApiCartDetailDto"}}}]}}}},"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"404":{"description":"The requested resource does not exist (`code: NOT_FOUND`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"Get a cart by its public id","tags":["Carts"]}},"/v1/carts/preview":{"post":{"description":"Stateless preview. Validates items + delivery area + split config and returns final totals. No cart row is created.","operationId":"CheckoutDevApiController_preview","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiCheckoutPreviewDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DevApiSuccessEnvelopeDto"},{"properties":{"data":{"$ref":"#/components/schemas/DevApiCheckoutPreviewResponseDto"}}}]}}}},"400":{"description":"Invalid request — malformed parameters or body (`code: BAD_REQUEST`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"404":{"description":"The requested resource does not exist (`code: NOT_FOUND`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"422":{"description":"The request is well-formed but cannot be processed (`code: UNPROCESSABLE_ENTITY`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"Compute cart totals without persisting anything","tags":["Carts"]}},"/v1/carts/{publicId}/pay":{"post":{"description":"Only usable when the previous POST /v1/carts call returned 502 PAYMENT_INIT_FAILED — i.e. the cart is in PENDING_PAYMENT with a pending payment row. Re-calls the payment provider with the same payment reference.","operationId":"CheckoutDevApiController_retryPay","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}},{"name":"publicId","required":true,"in":"path","schema":{"example":"CART-XPK39ZQA01","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiCheckoutRetryPayDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DevApiSuccessEnvelopeDto"},{"properties":{"data":{"$ref":"#/components/schemas/DevApiCheckoutRetryPayResponseDto"}}}]}}}},"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"404":{"description":"The requested resource does not exist (`code: NOT_FOUND`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"422":{"description":"The request is well-formed but cannot be processed (`code: UNPROCESSABLE_ENTITY`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"502":{"description":"The payment provider could not be reached (`code: PAYMENT_INIT_FAILED`). `data.cartPublicId` carries the created cart so the payment can be retried.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"Retry payment initialization for an existing cart","tags":["Carts"]}},"/v1/delivery-areas":{"get":{"description":"Returns every delivery area configured for the marketplace. Use an area `id` as `delivery.deliveryAreaId` when creating a cart with deliveryType = DELIVERY.","operationId":"DeliveryAreasDevApiController_list","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DevApiSuccessEnvelopeDto"},{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DevApiDeliveryAreaDto"}}}}]}}}},"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"List delivery areas","tags":["Delivery Areas"]}},"/v1/marketplace":{"get":{"description":"Returns the profile of the marketplace resolved from the API key: slug, business category and payment configuration (pay-on-delivery, split payment).","operationId":"MarketplaceDevApiController_getProfile","parameters":[{"name":"Authorization","in":"header","description":"Developer API key (Bearer xdk_…)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DevApiSuccessEnvelopeDto"},{"properties":{"data":{"$ref":"#/components/schemas/DevApiMarketplaceProfileDto"}}}]}}}},"401":{"description":"Missing or invalid developer API key\n\nMissing or invalid API key (`code: UNAUTHORIZED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"404":{"description":"The requested resource does not exist (`code: NOT_FOUND`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"429":{"description":"Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}},"500":{"description":"Unexpected server error (`code: INTERNAL_SERVER_ERROR`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevApiErrorEnvelopeDto"}}}}},"summary":"Get the marketplace profile","tags":["Marketplace"]}}},"info":{"title":"Xèdo Developer API","description":"Public REST API for merchants. Authenticate with a Bearer xdk_… key.","version":"1.0.0","contact":{}},"tags":[],"servers":[{"url":"http://localhost:5022"}],"components":{"securitySchemes":{"developer-api-key":{"scheme":"bearer","bearerFormat":"xdk_…","type":"http","description":"Developer API key issued from the merchant dashboard."}},"schemas":{"DevApiErrorEnvelopeDto":{"type":"object","properties":{"success":{"type":"boolean","example":false},"code":{"type":"string","example":"PRODUCT_NOT_FOUND","description":"Stable machine-readable error code. Safe to switch on in client code."},"message":{"type":"string","example":"Product not found","description":"Human-readable error message, translated when applicable."},"errors":{"type":"object","description":"Field-level validation errors, present when the error stems from input validation.","example":{"name":["name should not be empty"]}},"data":{"type":"object","description":"Contextual data attached to the error. For example, a PAYMENT_INIT_FAILED response carries the `cartPublicId` of the created cart so the payment can be retried via POST /v1/carts/{publicId}/pay.","example":{"cartPublicId":"CART-XPK39ZQA01"}}},"required":["success","code","message"]},"DevApiSuccessEnvelopeDto":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"}},"required":["success","data"]},"PingPayload":{"type":"object","properties":{"marketplaceId":{"type":"number","example":42},"timestamp":{"type":"string","example":"2026-05-26T13:14:15.000Z"}},"required":["marketplaceId","timestamp"]},"DevApiPaginatedEnvelopeDto":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"array"}},"total":{"type":"number","example":42,"description":"Total rows matching the query"},"start":{"type":"number","example":1,"description":"Index (1-based) of the first row returned"},"end":{"type":"number","example":10,"description":"Index (1-based) of the last row returned"}},"required":["success","data","total","start","end"]},"DevApiProductCollectionDto":{"type":"object","properties":{"name":{"type":"string","example":"Fast food"},"slug":{"type":"string","example":"fast-food"}},"required":["name","slug"]},"DevApiProductGalleryMediaDto":{"type":"object","properties":{"id":{"type":"number","example":1},"publicUrl":{"type":"string","example":"https://cdn.xedoapp.com/products/gallery/abc.jpg"},"type":{"type":"string","example":"image","enum":["image","video"]},"altText":{"type":"string","example":"Burger close-up"}},"required":["id","publicUrl","type"]},"DevApiProductVariationOptionDto":{"type":"object","properties":{"publicId":{"type":"string","example":"OPT_ABC123"},"name":{"type":"string","example":"XL"},"priceAdjustment":{"type":"number","example":500},"priceAdjustmentType":{"type":"string","enum":["fixed","percentage"],"example":"fixed"},"galleryMedias":{"type":"array","items":{"$ref":"#/components/schemas/DevApiProductGalleryMediaDto"}}},"required":["publicId","name","galleryMedias"]},"DevApiProductVariationDto":{"type":"object","properties":{"publicId":{"type":"string","example":"VAR_ABC123"},"variationTypeName":{"type":"string","example":"Taille"},"options":{"type":"array","items":{"$ref":"#/components/schemas/DevApiProductVariationOptionDto"}}},"required":["publicId","variationTypeName","options"]},"DevApiProductCombinationDto":{"type":"object","properties":{"publicId":{"type":"string","example":"COMB_ABC123"},"optionPublicIds":{"example":["OPT_ABC123","OPT_DEF456"],"description":"Public ids of the options forming this combination.","type":"array","items":{"type":"string"}},"stockQuantity":{"type":"number","example":10},"priceAdjustment":{"type":"number","example":500},"priceAdjustmentType":{"type":"string","enum":["fixed","percentage"],"example":"fixed"}},"required":["publicId","optionPublicIds","stockQuantity"]},"DevApiProductDto":{"type":"object","properties":{"publicId":{"type":"string","example":"6528412905"},"name":{"type":"string","example":"Burger"},"slug":{"type":"string","example":"burger"},"price":{"type":"number","example":10.5},"description":{"type":"string","example":"Delicious beef burger."},"coverUrl":{"type":"string","example":"https://cdn.xedoapp.com/products/cover/abc.jpg","nullable":true},"enabled":{"type":"boolean","example":true},"collection":{"$ref":"#/components/schemas/DevApiProductCollectionDto"},"createdAt":{"format":"date-time","type":"string","example":"2026-05-26T13:14:15.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-05-26T13:14:15.000Z"},"productSheet":{"type":"string","example":"Nutritional information"},"stockQuantity":{"type":"number","example":100},"trackStock":{"type":"boolean","example":true},"allowBackorder":{"type":"boolean","example":false},"lowStockThreshold":{"type":"number","example":10,"nullable":true},"splitOnlinePaymentPercentage":{"type":"number","example":30,"nullable":true,"description":"Percentage paid online for split payment. Null falls back to the marketplace default."},"galleryMedias":{"description":"Product gallery (image / video). Returned on detail endpoints.","type":"array","items":{"$ref":"#/components/schemas/DevApiProductGalleryMediaDto"}},"variations":{"description":"Variations (e.g. Size, Color) and their options.","type":"array","items":{"$ref":"#/components/schemas/DevApiProductVariationDto"}},"combinations":{"description":"Combinations (SKUs) with per-combination stock and pricing.","type":"array","items":{"$ref":"#/components/schemas/DevApiProductCombinationDto"}}},"required":["publicId","name","slug","price","enabled","collection","createdAt","updatedAt","stockQuantity","trackStock","allowBackorder"]},"DevApiCollectionDto":{"type":"object","properties":{"publicId":{"type":"string","example":"9023748120"},"name":{"type":"string","example":"Fast food"},"slug":{"type":"string","example":"fast-food"},"description":{"type":"string","example":"Quick bites & street food."},"coverUrl":{"type":"string","example":"https://cdn.xedoapp.com/collections/cover/abc.jpg","nullable":true},"createdAt":{"format":"date-time","type":"string","example":"2026-05-26T13:14:15.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-05-26T13:14:15.000Z"}},"required":["publicId","name","slug","createdAt","updatedAt"]},"DevApiOrderCustomerDto":{"type":"object","properties":{"firstName":{"type":"string","example":"Jean"},"lastName":{"type":"string","example":"Kouassi"},"email":{"type":"string","example":"jean@example.com"},"phone":{"type":"string","example":"+225 07 12 34 56 78"}}},"DevApiOrderPaymentDto":{"type":"object","properties":{"reference":{"type":"string","example":"PAY-2024-001"},"amount":{"type":"number","example":125000},"onlineAmount":{"type":"number","example":37500,"nullable":true,"description":"Online portion amount (split payment only)."},"status":{"type":"string","enum":["pending","processing","success","failed"],"example":"success"},"method":{"type":"string","enum":["external_wallet","loyalty_card","pay_on_delivery","split_payment"],"example":"external_wallet"}},"required":["reference","amount","status","method"]},"DevApiOrderListItemDto":{"type":"object","properties":{"id":{"type":"number","example":1,"description":"Order internal id"},"publicId":{"type":"string","example":"ORD-XPK39ZQA01","description":"Public id (cart publicId)."},"customer":{"$ref":"#/components/schemas/DevApiOrderCustomerDto"},"itemsCount":{"type":"number","example":5},"orderAmount":{"type":"number","example":125000},"deliveryCost":{"type":"number","example":1000},"payment":{"$ref":"#/components/schemas/DevApiOrderPaymentDto"},"deliveryType":{"type":"string","enum":["DELIVERY","PICKUP"],"nullable":true},"orderStatus":{"type":"string","enum":["PREPARING","IN_DELIVERY","DELIVERED","READY_FOR_PICKUP","PICKED_UP"],"nullable":true},"meta":{"type":"object","description":"Developer-supplied metadata attached at cart creation.","nullable":true,"example":{"internalOrderId":"ORD-12345"}},"createdAt":{"format":"date-time","type":"string","example":"2026-05-26T13:14:15.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-05-26T13:14:15.000Z"}},"required":["id","publicId","customer","itemsCount","orderAmount","deliveryCost","payment","createdAt","updatedAt"]},"DevApiOrderItemCombinationDto":{"type":"object","properties":{"sku":{"type":"string","example":"SKU-XL-RED"},"optionNames":{"example":["XL","Red"],"type":"array","items":{"type":"string"}},"priceAdjustment":{"type":"number","example":500},"priceAdjustmentType":{"type":"string","enum":["fixed","percentage"],"example":"fixed"}},"required":["sku","optionNames"]},"DevApiOrderItemDto":{"type":"object","properties":{"id":{"type":"number","example":1,"description":"Cart item internal id"},"productId":{"type":"number","example":283},"name":{"type":"string","example":"Samsung Galaxy A54"},"slug":{"type":"string","example":"samsung-galaxy-a54"},"price":{"type":"number","example":125000},"quantity":{"type":"number","example":1},"lineTotal":{"type":"number","example":125000},"coverUrl":{"type":"string","example":"https://cdn.xedoapp.com/products/cover/abc.jpg","nullable":true},"combinationPublicId":{"type":"string","example":"COMB_ABC123"},"combination":{"$ref":"#/components/schemas/DevApiOrderItemCombinationDto"}},"required":["id","productId","name","slug","price","quantity","lineTotal"]},"DevApiOrderTotalsDto":{"type":"object","properties":{"subtotal":{"type":"number","example":125000},"deliveryFees":{"type":"number","example":1000},"total":{"type":"number","example":126000}},"required":["subtotal","deliveryFees","total"]},"DevApiOrderDeliveryInfoDto":{"type":"object","properties":{"areaId":{"type":"number","example":1},"areaName":{"type":"string","example":"Cocody, Angré 7ème tranche"},"deliveryCost":{"type":"number","example":1000}},"required":["areaId","areaName","deliveryCost"]},"DevApiOrderDeliveryDto":{"type":"object","properties":{"deliveryType":{"type":"string","enum":["DELIVERY","PICKUP"],"example":"DELIVERY"},"deliveryInfo":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/DevApiOrderDeliveryInfoDto"}]},"additionalDetails":{"type":"string","example":"Appeler 30 minutes avant la livraison","nullable":true},"orderStatus":{"type":"string","enum":["PREPARING","IN_DELIVERY","DELIVERED","READY_FOR_PICKUP","PICKED_UP"],"example":"PREPARING"}},"required":["deliveryType","orderStatus"]},"DevApiOrderDetailDto":{"type":"object","properties":{"id":{"type":"number","example":1,"description":"Order internal id"},"publicId":{"type":"string","example":"ORD-XPK39ZQA01"},"status":{"type":"string","enum":["DRAFT","PENDING_PAYMENT","ABANDONED","PAYMENT_FAILED","PAYMENT_COMPLETED"],"example":"PAYMENT_COMPLETED"},"customer":{"$ref":"#/components/schemas/DevApiOrderCustomerDto"},"items":{"type":"array","items":{"$ref":"#/components/schemas/DevApiOrderItemDto"}},"totals":{"$ref":"#/components/schemas/DevApiOrderTotalsDto"},"payment":{"$ref":"#/components/schemas/DevApiOrderPaymentDto"},"delivery":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/DevApiOrderDeliveryDto"}]},"meta":{"type":"object","description":"Developer-supplied metadata attached at cart creation.","nullable":true,"example":{"internalOrderId":"ORD-12345"}},"createdAt":{"format":"date-time","type":"string","example":"2026-05-26T13:14:15.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-05-26T13:14:15.000Z"}},"required":["id","publicId","status","customer","items","totals","payment","createdAt","updatedAt"]},"DevApiCartCustomerDto":{"type":"object","properties":{"firstName":{"type":"string","example":"Jean"},"lastName":{"type":"string","example":"Kouassi"},"email":{"type":"string","example":"jean@example.com"},"phone":{"type":"string","example":"+225 07 12 34 56 78"}}},"DevApiCartListItemDto":{"type":"object","properties":{"id":{"type":"number","example":1,"description":"Cart internal id"},"publicId":{"type":"string","example":"CART-XPK39ZQA01"},"customer":{"$ref":"#/components/schemas/DevApiCartCustomerDto"},"itemsCount":{"type":"number","example":5},"cartAmount":{"type":"number","example":125000},"deliveryCost":{"type":"number","example":1000},"status":{"type":"string","enum":["PENDING_PAYMENT","ABANDONED","PAYMENT_FAILED","PAYMENT_COMPLETED"]},"deliveryType":{"type":"string","enum":["DELIVERY","PICKUP"],"nullable":true},"orderStatus":{"type":"string","enum":["PREPARING","IN_DELIVERY","DELIVERED","READY_FOR_PICKUP","PICKED_UP"],"nullable":true},"meta":{"type":"object","description":"Developer-supplied metadata attached at cart creation.","nullable":true,"example":{"internalOrderId":"ORD-12345"}},"createdAt":{"format":"date-time","type":"string","example":"2026-05-26T13:14:15.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-05-26T13:14:15.000Z"}},"required":["id","publicId","customer","itemsCount","cartAmount","deliveryCost","status","createdAt","updatedAt"]},"DevApiCartItemCombinationDto":{"type":"object","properties":{"sku":{"type":"string","example":"SKU-XL-RED"},"optionNames":{"example":["XL","Red"],"type":"array","items":{"type":"string"}},"priceAdjustment":{"type":"number","example":500},"priceAdjustmentType":{"type":"string","enum":["fixed","percentage"],"example":"fixed"}},"required":["sku","optionNames"]},"DevApiCartItemDto":{"type":"object","properties":{"id":{"type":"number","example":1,"description":"Cart item internal id"},"productId":{"type":"number","example":283},"name":{"type":"string","example":"Samsung Galaxy A54"},"slug":{"type":"string","example":"samsung-galaxy-a54"},"price":{"type":"number","example":125000},"quantity":{"type":"number","example":1},"lineTotal":{"type":"number","example":125000},"coverUrl":{"type":"string","example":"https://cdn.xedoapp.com/products/cover/abc.jpg","nullable":true},"combinationPublicId":{"type":"string","example":"COMB_ABC123"},"combination":{"$ref":"#/components/schemas/DevApiCartItemCombinationDto"}},"required":["id","productId","name","slug","price","quantity","lineTotal"]},"DevApiCartTotalsDto":{"type":"object","properties":{"subtotal":{"type":"number","example":125000},"deliveryFees":{"type":"number","example":1000},"total":{"type":"number","example":126000}},"required":["subtotal","deliveryFees","total"]},"DevApiCartDeliveryInfoDto":{"type":"object","properties":{"areaId":{"type":"number","example":1},"areaName":{"type":"string","example":"Cocody, Angré 7ème tranche"},"deliveryCost":{"type":"number","example":1000}},"required":["areaId","areaName","deliveryCost"]},"DevApiCartDeliveryDto":{"type":"object","properties":{"deliveryType":{"type":"string","enum":["DELIVERY","PICKUP"],"example":"DELIVERY"},"deliveryInfo":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/DevApiCartDeliveryInfoDto"}]},"additionalDetails":{"type":"string","example":"Appeler 30 minutes avant","nullable":true},"orderStatus":{"type":"string","enum":["PREPARING","IN_DELIVERY","DELIVERED","READY_FOR_PICKUP","PICKED_UP"],"example":"PREPARING"}},"required":["deliveryType","orderStatus"]},"DevApiCartDetailDto":{"type":"object","properties":{"id":{"type":"number","example":1,"description":"Cart internal id"},"publicId":{"type":"string","example":"CART-XPK39ZQA01"},"status":{"type":"string","enum":["PENDING_PAYMENT","ABANDONED","PAYMENT_FAILED","PAYMENT_COMPLETED"]},"customer":{"$ref":"#/components/schemas/DevApiCartCustomerDto"},"items":{"type":"array","items":{"$ref":"#/components/schemas/DevApiCartItemDto"}},"totals":{"$ref":"#/components/schemas/DevApiCartTotalsDto"},"delivery":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/DevApiCartDeliveryDto"}]},"meta":{"type":"object","description":"Developer-supplied metadata attached at cart creation.","nullable":true,"example":{"internalOrderId":"ORD-12345"}},"createdAt":{"format":"date-time","type":"string","example":"2026-05-26T13:14:15.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-05-26T13:14:15.000Z"}},"required":["id","publicId","status","customer","items","totals","createdAt","updatedAt"]},"DevApiCheckoutPreviewResponseDto":{"type":"object","properties":{"subtotal":{"type":"number","example":250000},"deliveryCost":{"type":"number","example":1000},"total":{"type":"number","example":251000},"onlineAmount":{"type":"number","example":150000,"nullable":true,"description":"Set only when paymentMethod = split_payment."},"onDeliveryAmount":{"type":"number","example":101000,"nullable":true,"description":"Set only when paymentMethod = split_payment."}},"required":["subtotal","deliveryCost","total"]},"DevApiCheckoutItemDto":{"type":"object","properties":{"publicProductId":{"type":"string","example":"9023748120"},"quantity":{"type":"number","example":2,"minimum":1},"combinationPublicId":{"type":"string","example":"COMB_ABC123"}},"required":["publicProductId","quantity"]},"DevApiCheckoutDeliveryDto":{"type":"object","properties":{"deliveryType":{"type":"string","enum":["DELIVERY","PICKUP"],"example":"DELIVERY"},"deliveryAreaId":{"type":"number","example":1,"description":"Required when deliveryType = DELIVERY."}},"required":["deliveryType"]},"DevApiCheckoutPreviewDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/DevApiCheckoutItemDto"}},"delivery":{"$ref":"#/components/schemas/DevApiCheckoutDeliveryDto"},"paymentMethod":{"type":"string","enum":["external_wallet","split_payment"],"example":"external_wallet"}},"required":["items","delivery","paymentMethod"]},"DevApiCheckoutTotalsDto":{"type":"object","properties":{"subtotal":{"type":"number","example":250000},"deliveryCost":{"type":"number","example":1000},"total":{"type":"number","example":251000},"onlineAmount":{"type":"number","example":150000,"nullable":true},"onDeliveryAmount":{"type":"number","example":101000,"nullable":true}},"required":["subtotal","deliveryCost","total"]},"DevApiCheckoutPaymentDto":{"type":"object","properties":{"reference":{"type":"string","example":"PAY-XPK39ZQA01"},"status":{"type":"string","example":"pending"}},"required":["reference","status"]},"DevApiCheckoutCreateResponseDto":{"type":"object","properties":{"publicId":{"type":"string","example":"CART-XPK39ZQA01"},"status":{"type":"string","example":"PENDING_PAYMENT"},"totals":{"$ref":"#/components/schemas/DevApiCheckoutTotalsDto"},"payment":{"$ref":"#/components/schemas/DevApiCheckoutPaymentDto"},"checkoutUrl":{"type":"string","example":"https://checkout.moneroo.io/abc-def"}},"required":["publicId","status","totals","payment","checkoutUrl"]},"DevApiCheckoutCustomerDto":{"type":"object","properties":{"firstName":{"type":"string","example":"Jean"},"lastName":{"type":"string","example":"Kouassi"},"email":{"type":"string","example":"jean@example.com"},"phone":{"type":"string","example":"+225 07 12 34 56 78"}},"required":["firstName","lastName","email","phone"]},"DevApiCheckoutCreateDto":{"type":"object","properties":{"customer":{"$ref":"#/components/schemas/DevApiCheckoutCustomerDto"},"items":{"type":"array","items":{"$ref":"#/components/schemas/DevApiCheckoutItemDto"}},"delivery":{"$ref":"#/components/schemas/DevApiCheckoutDeliveryDto"},"paymentMethod":{"type":"string","enum":["external_wallet","split_payment"],"example":"external_wallet"},"returnUrl":{"type":"string","example":"https://my-app.com/after-checkout","description":"URL to redirect the customer to after the payment provider checkout. Must be HTTPS."},"additionalDetails":{"type":"string","example":"Appeler 30 min avant"},"meta":{"type":"object","description":"Free-form JSON payload returned as-is in every cart/order response. Use it to attach your own identifiers (e.g. internalOrderId).","example":{"internalOrderId":"ORD-12345","source":"mobile-app"}}},"required":["customer","items","delivery","paymentMethod","returnUrl"]},"DevApiCheckoutRetryPayResponseDto":{"type":"object","properties":{"payment":{"$ref":"#/components/schemas/DevApiCheckoutPaymentDto"},"checkoutUrl":{"type":"string","example":"https://checkout.moneroo.io/abc-def"}},"required":["payment","checkoutUrl"]},"DevApiCheckoutRetryPayDto":{"type":"object","properties":{"returnUrl":{"type":"string","example":"https://my-app.com/after-checkout"}},"required":["returnUrl"]},"DevApiDeliveryAreaDto":{"type":"object","properties":{"id":{"type":"number","example":1,"description":"Identifier to pass as `delivery.deliveryAreaId` when creating a cart."},"name":{"type":"string","example":"Cocody"},"deliveryCost":{"type":"number","example":1000,"description":"Delivery cost for this area."}},"required":["id","name","deliveryCost"]},"DevApiBusinessCategoryDto":{"type":"object","properties":{"id":{"type":"number","example":3},"name":{"type":"string","example":"Restauration"}},"required":["id","name"]},"DevApiMarketplaceProfileDto":{"type":"object","properties":{"slug":{"type":"string","example":"ma-boutique"},"enabled":{"type":"boolean","example":true},"businessCategory":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/DevApiBusinessCategoryDto"}]},"whatsappPhoneNumber":{"type":"string","example":"+225 07 12 34 56 78","nullable":true},"enablePayOnDelivery":{"type":"boolean","example":true},"enableSplitPayment":{"type":"boolean","example":true},"defaultOnlineSplitPaymentPercentage":{"type":"number","example":30,"nullable":true,"description":"Default percentage paid online for split payment. Null if split payment is disabled."},"splitPaymentDeliveryCostHandling":{"type":"string","enum":["online","on_delivery"],"example":"on_delivery","description":"Whether the delivery cost is paid online or on delivery in a split payment."},"createdAt":{"format":"date-time","type":"string","example":"2026-05-26T13:14:15.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2026-05-26T13:14:15.000Z"}},"required":["slug","enabled","enablePayOnDelivery","enableSplitPayment","splitPaymentDeliveryCostHandling","createdAt","updatedAt"]}}}} \ No newline at end of file diff --git a/src/client.ts b/src/client.ts index 194ecc2..c47a594 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,6 +1,8 @@ import { XedoConnectionError, XedoError } from './errors'; import { Carts } from './resources/carts'; import { Collections } from './resources/collections'; +import { DeliveryAreas } from './resources/delivery-areas'; +import { Marketplace } from './resources/marketplace'; import { Orders } from './resources/orders'; import { Products } from './resources/products'; import { Transport, type FetchLike } from './transport'; @@ -42,6 +44,8 @@ export class Xedo { readonly collections: Collections; readonly orders: Orders; readonly carts: Carts; + readonly deliveryAreas: DeliveryAreas; + readonly marketplace: Marketplace; private readonly apiKey: string; private readonly transport: Transport; @@ -91,6 +95,8 @@ export class Xedo { this.collections = new Collections(this.transport); this.orders = new Orders(this.transport); this.carts = new Carts(this.transport); + this.deliveryAreas = new DeliveryAreas(this.transport); + this.marketplace = new Marketplace(this.transport); } /** diff --git a/src/index.ts b/src/index.ts index fb408c1..17f047e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,13 +17,46 @@ export { export type { JsonObject, SortOrder, + // Enums + OrderStatus, + CartStatus, + FulfillmentStatus, + DeliveryType, + PaymentStatus, + OrderPaymentMethod, + PriceAdjustmentType, + MediaType, + // Entities PingResult, Product, + ProductCollection, + ProductGalleryMedia, + ProductVariation, + ProductVariationOption, + ProductCombination, Collection, Order, + OrderListItem, + OrderCustomer, + OrderPayment, + OrderItem, + OrderTotals, + OrderDelivery, Cart, + CartListItem, + CartCustomer, + CartItem, + CartTotals, + CartDelivery, CheckoutPreview, + CheckoutTotals, + CheckoutPayment, CheckoutResult, + CheckoutRetryResult, + DeliveryArea, + BusinessCategory, + MarketplaceProfile, + // List / request params ListParams, ProductListParams, CollectionListParams, @@ -33,6 +66,7 @@ export type { RequestOptions, PaginatedResult, RateLimitInfo, + // Checkout inputs CheckoutItem, CheckoutDelivery, CheckoutCustomer, diff --git a/src/resources/carts.ts b/src/resources/carts.ts index 8189d6d..b854db3 100644 --- a/src/resources/carts.ts +++ b/src/resources/carts.ts @@ -2,30 +2,32 @@ import { paginate, Resource, toListQuery } from './base'; import { XedoPaymentInitError } from '../errors'; import type { Cart, + CartListItem, CartListParams, CheckoutCreateInput, CheckoutPreview, CheckoutPreviewInput, CheckoutResult, CheckoutRetryPayInput, + CheckoutRetryResult, PaginatedResult, RequestOptions, } from '../types/public'; export class Carts extends Resource { /** - * `GET /v1/carts` — one page of carts. `DRAFT` carts are never exposed by - * the API. + * `GET /v1/carts` — one page of carts (summary rows). `DRAFT` carts are + * never exposed by the API. */ - list(params: CartListParams = {}): Promise> { - return this.transport.getPage('/v1/carts', { + list(params: CartListParams = {}): Promise> { + return this.transport.getPage('/v1/carts', { query: toListQuery(params), signal: params.signal, }); } - /** Async iterator over every cart across all pages. */ - listAll(params: CartListParams = {}): AsyncGenerator { + /** Async iterator over every cart (summary row) across all pages. */ + listAll(params: CartListParams = {}): AsyncGenerator { return paginate((p) => this.list(p), params); } @@ -60,8 +62,8 @@ export class Carts extends Resource { * `POST /v1/carts/{publicId}/pay` — relaunch payment initialization after a * `502 PAYMENT_INIT_FAILED`. */ - pay(publicId: string, input: CheckoutRetryPayInput, opts: RequestOptions = {}): Promise { - return this.transport.getData( + pay(publicId: string, input: CheckoutRetryPayInput, opts: RequestOptions = {}): Promise { + return this.transport.getData( 'POST', `/v1/carts/${encodeURIComponent(publicId)}/pay`, { body: input, signal: opts.signal }, @@ -73,8 +75,15 @@ export class Carts extends Resource { * the payment provider could not be reached (`PAYMENT_INIT_FAILED`), retry * `pay()` once with the same `returnUrl`. Stays transparent — it logs the * code and never swallows a definitive failure. + * + * Returns a {@link CheckoutResult} on the happy path, or a + * {@link CheckoutRetryResult} when the retry succeeded — both carry + * `checkoutUrl` and `payment`. */ - async createAndPay(input: CheckoutCreateInput, opts: RequestOptions = {}): Promise { + async createAndPay( + input: CheckoutCreateInput, + opts: RequestOptions = {}, + ): Promise { try { return await this.create(input, opts); } catch (err) { diff --git a/src/resources/delivery-areas.ts b/src/resources/delivery-areas.ts new file mode 100644 index 0000000..0e6c9a6 --- /dev/null +++ b/src/resources/delivery-areas.ts @@ -0,0 +1,14 @@ +import { Resource } from './base'; +import type { DeliveryArea, RequestOptions } from '../types/public'; + +export class DeliveryAreas extends Resource { + /** + * `GET /v1/delivery-areas` — every delivery area configured by the merchant. + * Use a returned `id` as `delivery.deliveryAreaId` when creating a cart. + */ + list(opts: RequestOptions = {}): Promise { + return this.transport.getData('GET', '/v1/delivery-areas', { + signal: opts.signal, + }); + } +} diff --git a/src/resources/marketplace.ts b/src/resources/marketplace.ts new file mode 100644 index 0000000..ca13a5e --- /dev/null +++ b/src/resources/marketplace.ts @@ -0,0 +1,14 @@ +import { Resource } from './base'; +import type { MarketplaceProfile, RequestOptions } from '../types/public'; + +export class Marketplace extends Resource { + /** + * `GET /v1/marketplace` — the merchant's marketplace profile: enabled + * payment methods, split-payment configuration, business category, … + */ + retrieve(opts: RequestOptions = {}): Promise { + return this.transport.getData('GET', '/v1/marketplace', { + signal: opts.signal, + }); + } +} diff --git a/src/resources/orders.ts b/src/resources/orders.ts index 8672413..0cfe464 100644 --- a/src/resources/orders.ts +++ b/src/resources/orders.ts @@ -1,17 +1,17 @@ import { paginate, Resource, toListQuery } from './base'; -import type { Order, OrderListParams, PaginatedResult, RequestOptions } from '../types/public'; +import type { Order, OrderListItem, OrderListParams, PaginatedResult, RequestOptions } from '../types/public'; export class Orders extends Resource { - /** `GET /v1/orders` — one page of paid orders. */ - list(params: OrderListParams = {}): Promise> { - return this.transport.getPage('/v1/orders', { + /** `GET /v1/orders` — one page of paid orders (summary rows). */ + list(params: OrderListParams = {}): Promise> { + return this.transport.getPage('/v1/orders', { query: toListQuery(params), signal: params.signal, }); } - /** Async iterator over every order across all pages. */ - listAll(params: OrderListParams = {}): AsyncGenerator { + /** Async iterator over every order (summary row) across all pages. */ + listAll(params: OrderListParams = {}): AsyncGenerator { return paginate((p) => this.list(p), params); } diff --git a/src/types/generated.ts b/src/types/generated.ts index 113b1d1..435189f 100644 --- a/src/types/generated.ts +++ b/src/types/generated.ts @@ -12,10 +12,10 @@ export interface paths { cookie?: never; }; /** - * Vérifier la clé API - * @description Renvoie l'identifiant du marketplace résolu depuis la clé fournie. Utilisez cet endpoint pour valider votre clé de bout en bout. + * Authenticated ping + * @description Returns the marketplace id resolved from the provided API key. Use it to verify that your key works end-to-end. */ - get: operations["ping"]; + get: operations["DevApiPingController_ping"]; put?: never; post?: never; delete?: never; @@ -32,10 +32,10 @@ export interface paths { cookie?: never; }; /** - * Lister les produits - * @description Renvoie les produits du marchand (paginés). Par défaut, seuls les produits activés sont retournés — passez `includeDisabled=true` pour inclure également les brouillons. + * List products + * @description Returns the marchant's products (paginated). By default only enabled products are returned — set `includeDisabled=true` to also return drafts. */ - get: operations["listProducts"]; + get: operations["ProductsDevApiController_list"]; put?: never; post?: never; delete?: never; @@ -52,10 +52,10 @@ export interface paths { cookie?: never; }; /** - * Récupérer un produit par son identifiant public - * @description Renvoie un produit unique (avec variations, combinaisons et galerie). Passez `includeDisabled=true` pour résoudre également les brouillons. + * Get a product by its public id + * @description Returns a single product (with variations, combinations and gallery). Set `includeDisabled=true` to also resolve drafts. */ - get: operations["getProductByPublicId"]; + get: operations["ProductsDevApiController_getByPublicId"]; put?: never; post?: never; delete?: never; @@ -72,10 +72,10 @@ export interface paths { cookie?: never; }; /** - * Récupérer un produit par son slug - * @description Renvoie un produit unique recherché par son slug URL-friendly. Passez `includeDisabled=true` pour résoudre également les brouillons. + * Get a product by slug + * @description Returns a single product looked up by its URL-friendly slug. Set `includeDisabled=true` to also resolve drafts. */ - get: operations["getProductBySlug"]; + get: operations["ProductsDevApiController_getBySlug"]; put?: never; post?: never; delete?: never; @@ -92,10 +92,10 @@ export interface paths { cookie?: never; }; /** - * Lister les collections - * @description Renvoie les collections du marchand (paginées). Supporte le tri et la recherche par nom. + * List collections + * @description Returns the marchant's collections (paginated). Supports sorting and search by name. */ - get: operations["listCollections"]; + get: operations["CollectionsDevApiController_list"]; put?: never; post?: never; delete?: never; @@ -111,8 +111,8 @@ export interface paths { path?: never; cookie?: never; }; - /** Récupérer une collection par son identifiant public */ - get: operations["getCollectionByPublicId"]; + /** Get a collection by its public id */ + get: operations["CollectionsDevApiController_getByPublicId"]; put?: never; post?: never; delete?: never; @@ -128,8 +128,8 @@ export interface paths { path?: never; cookie?: never; }; - /** Récupérer une collection par son slug */ - get: operations["getCollectionBySlug"]; + /** Get a collection by slug */ + get: operations["CollectionsDevApiController_getBySlug"]; put?: never; post?: never; delete?: never; @@ -146,10 +146,10 @@ export interface paths { cookie?: never; }; /** - * Lister les commandes - * @description Renvoie les commandes du marchand (paniers payés) paginées. Supporte la recherche sur le `publicId` de commande, la référence de paiement et les données client. + * List orders + * @description Returns the merchant's orders (paid carts) paginated. Supports search on order publicId, payment reference and customer data. */ - get: operations["listOrders"]; + get: operations["OrdersDevApiController_list"]; put?: never; post?: never; delete?: never; @@ -166,10 +166,10 @@ export interface paths { cookie?: never; }; /** - * Récupérer une commande par son identifiant public - * @description Renvoie le détail d'une commande (items, totaux, paiement, livraison). + * Get an order by its public id + * @description Returns the order detail (items, totals, payment, delivery). */ - get: operations["getOrderByPublicId"]; + get: operations["OrdersDevApiController_getByPublicId"]; put?: never; post?: never; delete?: never; @@ -186,10 +186,10 @@ export interface paths { cookie?: never; }; /** - * Télécharger la facture (PDF) - * @description Renvoie la facture de la commande au format PDF (`application/pdf`). Renvoie 404 si aucune facture n'a encore été générée. + * Download the order invoice (PDF) + * @description Streams the order invoice as a PDF. Returns 404 if no invoice has been generated yet. */ - get: operations["getOrderInvoice"]; + get: operations["OrdersDevApiController_getInvoice"]; put?: never; post?: never; delete?: never; @@ -206,16 +206,16 @@ export interface paths { cookie?: never; }; /** - * Lister les paniers - * @description Renvoie les paniers du marchand (paginés). Les paniers `DRAFT` sont réservés à un usage interne et ne sont jamais exposés. + * List carts + * @description Returns the merchant's carts (paginated). DRAFT carts are reserved for internal usage and are never exposed. */ - get: operations["listCarts"]; + get: operations["CartsDevApiController_list"]; put?: never; /** - * Créer un panier et initier le paiement - * @description Crée un panier en `PENDING_PAYMENT` avec le client / les items / la livraison fournis, génère une ligne de paiement et demande une URL de checkout au provider de paiement. Si l'appel provider échoue, le panier est conservé et un `502 PAYMENT_INIT_FAILED` est retourné — relancez via `POST /v1/carts/{publicId}/pay`. + * Create a cart and initiate its payment in one call + * @description Creates a PENDING_PAYMENT cart with the given customer/items/delivery, generates a payment row, and asks the payment provider for a checkout URL. If the provider call fails, the cart is kept and a 502 PAYMENT_INIT_FAILED is returned — retry via POST /v1/carts/{publicId}/pay. */ - post: operations["createCart"]; + post: operations["CheckoutDevApiController_create"]; delete?: never; options?: never; head?: never; @@ -230,10 +230,10 @@ export interface paths { cookie?: never; }; /** - * Récupérer un panier par son identifiant public - * @description Renvoie le détail d'un panier (items, totaux, livraison). + * Get a cart by its public id + * @description Returns the cart detail (items, totals, delivery info). */ - get: operations["getCartByPublicId"]; + get: operations["CartsDevApiController_getByPublicId"]; put?: never; post?: never; delete?: never; @@ -252,10 +252,10 @@ export interface paths { get?: never; put?: never; /** - * Calculer les totaux d'un panier sans le persister - * @description Prévisualisation sans état. Valide les items, la zone de livraison et la configuration split, puis renvoie les totaux finaux. Aucun panier n'est créé. + * Compute cart totals without persisting anything + * @description Stateless preview. Validates items + delivery area + split config and returns final totals. No cart row is created. */ - post: operations["previewCart"]; + post: operations["CheckoutDevApiController_preview"]; delete?: never; options?: never; head?: never; @@ -272,10 +272,50 @@ export interface paths { get?: never; put?: never; /** - * Relancer l'initialisation du paiement d'un panier existant - * @description À utiliser uniquement lorsque l'appel précédent à `POST /v1/carts` a renvoyé `502 PAYMENT_INIT_FAILED` — c'est-à-dire que le panier est en `PENDING_PAYMENT` avec une ligne de paiement en attente. Re-sollicite le provider de paiement avec la même référence. + * Retry payment initialization for an existing cart + * @description Only usable when the previous POST /v1/carts call returned 502 PAYMENT_INIT_FAILED — i.e. the cart is in PENDING_PAYMENT with a pending payment row. Re-calls the payment provider with the same payment reference. */ - post: operations["retryCartPayment"]; + post: operations["CheckoutDevApiController_retryPay"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/delivery-areas": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List delivery areas + * @description Returns every delivery area configured for the marketplace. Use an area `id` as `delivery.deliveryAreaId` when creating a cart with deliveryType = DELIVERY. + */ + get: operations["DeliveryAreasDevApiController_list"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/marketplace": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get the marketplace profile + * @description Returns the profile of the marketplace resolved from the API key: slug, business category and payment configuration (pay-on-delivery, split payment). + */ + get: operations["MarketplaceDevApiController_getProfile"]; + put?: never; + post?: never; delete?: never; options?: never; head?: never; @@ -286,102 +326,618 @@ export interface paths { export type webhooks = Record; export interface components { schemas: { - /** @description Enveloppe de réponse standard pour une ressource unique. */ + DevApiErrorEnvelopeDto: { + /** @example false */ + success: boolean; + /** + * @description Stable machine-readable error code. Safe to switch on in client code. + * @example PRODUCT_NOT_FOUND + */ + code: string; + /** + * @description Human-readable error message, translated when applicable. + * @example Product not found + */ + message: string; + /** + * @description Field-level validation errors, present when the error stems from input validation. + * @example { + * "name": [ + * "name should not be empty" + * ] + * } + */ + errors?: Record; + /** + * @description Contextual data attached to the error. For example, a PAYMENT_INIT_FAILED response carries the `cartPublicId` of the created cart so the payment can be retried via POST /v1/carts/{publicId}/pay. + * @example { + * "cartPublicId": "CART-XPK39ZQA01" + * } + */ + data?: Record; + }; DevApiSuccessEnvelopeDto: { /** @example true */ success: boolean; - /** @description Charge utile de la réponse. */ data: Record; }; - /** @description Enveloppe de réponse standard pour une collection paginée. Le header `Content-Range` accompagne toujours cette réponse. */ + PingPayload: { + /** @example 42 */ + marketplaceId: number; + /** @example 2026-05-26T13:14:15.000Z */ + timestamp: string; + }; DevApiPaginatedEnvelopeDto: { /** @example true */ success: boolean; - /** @description Tableau d'éléments pour la page courante. */ - data: Record[]; + data: unknown[][]; /** - * @description Nombre total de lignes correspondant à la requête. + * @description Total rows matching the query * @example 42 */ total: number; /** - * @description Index (1-based) de la première ligne renvoyée. + * @description Index (1-based) of the first row returned * @example 1 */ start: number; /** - * @description Index (1-based) de la dernière ligne renvoyée. + * @description Index (1-based) of the last row returned * @example 10 */ end: number; }; - /** @description Enveloppe d'erreur standard. Le champ `errors` (optionnel) détaille les violations par champ pour les erreurs de validation. */ - DevApiErrorEnvelopeDto: { + DevApiProductCollectionDto: { + /** @example Fast food */ + name: string; + /** @example fast-food */ + slug: string; + }; + DevApiProductGalleryMediaDto: { + /** @example 1 */ + id: number; + /** @example https://cdn.xedoapp.com/products/gallery/abc.jpg */ + publicUrl: string; + /** + * @example image + * @enum {string} + */ + type: "image" | "video"; + /** @example Burger close-up */ + altText?: string; + }; + DevApiProductVariationOptionDto: { + /** @example OPT_ABC123 */ + publicId: string; + /** @example XL */ + name: string; + /** @example 500 */ + priceAdjustment?: number; + /** + * @example fixed + * @enum {string} + */ + priceAdjustmentType?: "fixed" | "percentage"; + galleryMedias: components["schemas"]["DevApiProductGalleryMediaDto"][]; + }; + DevApiProductVariationDto: { + /** @example VAR_ABC123 */ + publicId: string; + /** @example Taille */ + variationTypeName: string; + options: components["schemas"]["DevApiProductVariationOptionDto"][]; + }; + DevApiProductCombinationDto: { + /** @example COMB_ABC123 */ + publicId: string; + /** + * @description Public ids of the options forming this combination. + * @example [ + * "OPT_ABC123", + * "OPT_DEF456" + * ] + */ + optionPublicIds: string[]; + /** @example 10 */ + stockQuantity: number; + /** @example 500 */ + priceAdjustment?: number; + /** + * @example fixed + * @enum {string} + */ + priceAdjustmentType?: "fixed" | "percentage"; + }; + DevApiProductDto: { + /** @example 6528412905 */ + publicId: string; + /** @example Burger */ + name: string; + /** @example burger */ + slug: string; + /** @example 10.5 */ + price: number; + /** @example Delicious beef burger. */ + description?: string; + /** @example https://cdn.xedoapp.com/products/cover/abc.jpg */ + coverUrl?: string | null; + /** @example true */ + enabled: boolean; + collection: components["schemas"]["DevApiProductCollectionDto"]; + /** + * Format: date-time + * @example 2026-05-26T13:14:15.000Z + */ + createdAt: string; + /** + * Format: date-time + * @example 2026-05-26T13:14:15.000Z + */ + updatedAt: string; + /** @example Nutritional information */ + productSheet?: string; + /** @example 100 */ + stockQuantity: number; + /** @example true */ + trackStock: boolean; /** @example false */ - success: boolean; + allowBackorder: boolean; + /** @example 10 */ + lowStockThreshold?: number | null; /** - * @description Code d'erreur machine-readable. Voir la page Ressources › Erreurs pour la liste complète. - * @example PRODUCT_NOT_FOUND + * @description Percentage paid online for split payment. Null falls back to the marketplace default. + * @example 30 */ - code: string; + splitOnlinePaymentPercentage?: number | null; + /** @description Product gallery (image / video). Returned on detail endpoints. */ + galleryMedias?: components["schemas"]["DevApiProductGalleryMediaDto"][]; + /** @description Variations (e.g. Size, Color) and their options. */ + variations?: components["schemas"]["DevApiProductVariationDto"][]; + /** @description Combinations (SKUs) with per-combination stock and pricing. */ + combinations?: components["schemas"]["DevApiProductCombinationDto"][]; + }; + DevApiCollectionDto: { + /** @example 9023748120 */ + publicId: string; + /** @example Fast food */ + name: string; + /** @example fast-food */ + slug: string; + /** @example Quick bites & street food. */ + description?: string; + /** @example https://cdn.xedoapp.com/collections/cover/abc.jpg */ + coverUrl?: string | null; /** - * @description Message lisible par un humain (français). - * @example Le produit n'a pas été trouvé + * Format: date-time + * @example 2026-05-26T13:14:15.000Z */ - message: string; - /** @description Détail des violations par champ (uniquement pour les erreurs de validation). */ - errors?: { - [key: string]: string[]; - }; - /** @description Contexte additionnel optionnel (ex. `cartPublicId` sur `PAYMENT_INIT_FAILED`). */ - data?: Record; + createdAt: string; + /** + * Format: date-time + * @example 2026-05-26T13:14:15.000Z + */ + updatedAt: string; }; - DevApiCheckoutItemDto: { - /** @example PRD-XPK39ZQA01 */ - publicProductId: string; - /** @example 2 */ - quantity: number; + DevApiOrderCustomerDto: { + /** @example Jean */ + firstName?: string; + /** @example Kouassi */ + lastName?: string; + /** @example jean@example.com */ + email?: string; + /** @example +225 07 12 34 56 78 */ + phone?: string; + }; + DevApiOrderPaymentDto: { + /** @example PAY-2024-001 */ + reference: string; + /** @example 125000 */ + amount: number; + /** + * @description Online portion amount (split payment only). + * @example 37500 + */ + onlineAmount?: number | null; + /** + * @example success + * @enum {string} + */ + status: "pending" | "processing" | "success" | "failed"; + /** + * @example external_wallet + * @enum {string} + */ + method: "external_wallet" | "loyalty_card" | "pay_on_delivery" | "split_payment"; + }; + DevApiOrderListItemDto: { + /** + * @description Order internal id + * @example 1 + */ + id: number; + /** + * @description Public id (cart publicId). + * @example ORD-XPK39ZQA01 + */ + publicId: string; + customer: components["schemas"]["DevApiOrderCustomerDto"]; + /** @example 5 */ + itemsCount: number; + /** @example 125000 */ + orderAmount: number; + /** @example 1000 */ + deliveryCost: number; + payment: components["schemas"]["DevApiOrderPaymentDto"]; + /** @enum {string|null} */ + deliveryType?: "DELIVERY" | "PICKUP" | null; + /** @enum {string|null} */ + orderStatus?: "PREPARING" | "IN_DELIVERY" | "DELIVERED" | "READY_FOR_PICKUP" | "PICKED_UP" | null; + /** + * @description Developer-supplied metadata attached at cart creation. + * @example { + * "internalOrderId": "ORD-12345" + * } + */ + meta?: Record | null; + /** + * Format: date-time + * @example 2026-05-26T13:14:15.000Z + */ + createdAt: string; + /** + * Format: date-time + * @example 2026-05-26T13:14:15.000Z + */ + updatedAt: string; + }; + DevApiOrderItemCombinationDto: { + /** @example SKU-XL-RED */ + sku: string; + /** + * @example [ + * "XL", + * "Red" + * ] + */ + optionNames: string[]; + /** @example 500 */ + priceAdjustment?: number; + /** + * @example fixed + * @enum {string} + */ + priceAdjustmentType?: "fixed" | "percentage"; + }; + DevApiOrderItemDto: { /** - * @description Identifiant public de la combinaison (SKU) si le produit a des variations. - * @example COMB-ABC123 + * @description Cart item internal id + * @example 1 */ + id: number; + /** @example 283 */ + productId: number; + /** @example Samsung Galaxy A54 */ + name: string; + /** @example samsung-galaxy-a54 */ + slug: string; + /** @example 125000 */ + price: number; + /** @example 1 */ + quantity: number; + /** @example 125000 */ + lineTotal: number; + /** @example https://cdn.xedoapp.com/products/cover/abc.jpg */ + coverUrl?: string | null; + /** @example COMB_ABC123 */ combinationPublicId?: string; + combination?: components["schemas"]["DevApiOrderItemCombinationDto"]; + }; + DevApiOrderTotalsDto: { + /** @example 125000 */ + subtotal: number; + /** @example 1000 */ + deliveryFees: number; + /** @example 126000 */ + total: number; }; - DevApiCheckoutDeliveryDto: { + DevApiOrderDeliveryInfoDto: { + /** @example 1 */ + areaId: number; + /** @example Cocody, Angré 7ème tranche */ + areaName: string; + /** @example 1000 */ + deliveryCost: number; + }; + DevApiOrderDeliveryDto: { /** * @example DELIVERY * @enum {string} */ deliveryType: "DELIVERY" | "PICKUP"; + deliveryInfo?: components["schemas"]["DevApiOrderDeliveryInfoDto"] | null; + /** @example Appeler 30 minutes avant la livraison */ + additionalDetails?: string | null; /** - * @description Requis lorsque `deliveryType = DELIVERY`. - * @example 11 + * @example PREPARING + * @enum {string} */ - deliveryAreaId?: number; + orderStatus: "PREPARING" | "IN_DELIVERY" | "DELIVERED" | "READY_FOR_PICKUP" | "PICKED_UP"; }; - DevApiCheckoutCustomerDto: { + DevApiOrderDetailDto: { + /** + * @description Order internal id + * @example 1 + */ + id: number; + /** @example ORD-XPK39ZQA01 */ + publicId: string; + /** + * @example PAYMENT_COMPLETED + * @enum {string} + */ + status: "DRAFT" | "PENDING_PAYMENT" | "ABANDONED" | "PAYMENT_FAILED" | "PAYMENT_COMPLETED"; + customer: components["schemas"]["DevApiOrderCustomerDto"]; + items: components["schemas"]["DevApiOrderItemDto"][]; + totals: components["schemas"]["DevApiOrderTotalsDto"]; + payment: components["schemas"]["DevApiOrderPaymentDto"]; + delivery?: components["schemas"]["DevApiOrderDeliveryDto"] | null; + /** + * @description Developer-supplied metadata attached at cart creation. + * @example { + * "internalOrderId": "ORD-12345" + * } + */ + meta?: Record | null; + /** + * Format: date-time + * @example 2026-05-26T13:14:15.000Z + */ + createdAt: string; + /** + * Format: date-time + * @example 2026-05-26T13:14:15.000Z + */ + updatedAt: string; + }; + DevApiCartCustomerDto: { /** @example Jean */ - firstName: string; + firstName?: string; /** @example Kouassi */ - lastName: string; + lastName?: string; + /** @example jean@example.com */ + email?: string; + /** @example +225 07 12 34 56 78 */ + phone?: string; + }; + DevApiCartListItemDto: { /** - * Format: email - * @example jean@example.com + * @description Cart internal id + * @example 1 */ - email: string; - /** @example +225 07 12 34 56 78 */ - phone: string; + id: number; + /** @example CART-XPK39ZQA01 */ + publicId: string; + customer: components["schemas"]["DevApiCartCustomerDto"]; + /** @example 5 */ + itemsCount: number; + /** @example 125000 */ + cartAmount: number; + /** @example 1000 */ + deliveryCost: number; + /** @enum {string} */ + status: "PENDING_PAYMENT" | "ABANDONED" | "PAYMENT_FAILED" | "PAYMENT_COMPLETED"; + /** @enum {string|null} */ + deliveryType?: "DELIVERY" | "PICKUP" | null; + /** @enum {string|null} */ + orderStatus?: "PREPARING" | "IN_DELIVERY" | "DELIVERED" | "READY_FOR_PICKUP" | "PICKED_UP" | null; + /** + * @description Developer-supplied metadata attached at cart creation. + * @example { + * "internalOrderId": "ORD-12345" + * } + */ + meta?: Record | null; + /** + * Format: date-time + * @example 2026-05-26T13:14:15.000Z + */ + createdAt: string; + /** + * Format: date-time + * @example 2026-05-26T13:14:15.000Z + */ + updatedAt: string; + }; + DevApiCartItemCombinationDto: { + /** @example SKU-XL-RED */ + sku: string; + /** + * @example [ + * "XL", + * "Red" + * ] + */ + optionNames: string[]; + /** @example 500 */ + priceAdjustment?: number; + /** + * @example fixed + * @enum {string} + */ + priceAdjustmentType?: "fixed" | "percentage"; + }; + DevApiCartItemDto: { + /** + * @description Cart item internal id + * @example 1 + */ + id: number; + /** @example 283 */ + productId: number; + /** @example Samsung Galaxy A54 */ + name: string; + /** @example samsung-galaxy-a54 */ + slug: string; + /** @example 125000 */ + price: number; + /** @example 1 */ + quantity: number; + /** @example 125000 */ + lineTotal: number; + /** @example https://cdn.xedoapp.com/products/cover/abc.jpg */ + coverUrl?: string | null; + /** @example COMB_ABC123 */ + combinationPublicId?: string; + combination?: components["schemas"]["DevApiCartItemCombinationDto"]; + }; + DevApiCartTotalsDto: { + /** @example 125000 */ + subtotal: number; + /** @example 1000 */ + deliveryFees: number; + /** @example 126000 */ + total: number; + }; + DevApiCartDeliveryInfoDto: { + /** @example 1 */ + areaId: number; + /** @example Cocody, Angré 7ème tranche */ + areaName: string; + /** @example 1000 */ + deliveryCost: number; + }; + DevApiCartDeliveryDto: { + /** + * @example DELIVERY + * @enum {string} + */ + deliveryType: "DELIVERY" | "PICKUP"; + deliveryInfo?: components["schemas"]["DevApiCartDeliveryInfoDto"] | null; + /** @example Appeler 30 minutes avant */ + additionalDetails?: string | null; + /** + * @example PREPARING + * @enum {string} + */ + orderStatus: "PREPARING" | "IN_DELIVERY" | "DELIVERED" | "READY_FOR_PICKUP" | "PICKED_UP"; + }; + DevApiCartDetailDto: { + /** + * @description Cart internal id + * @example 1 + */ + id: number; + /** @example CART-XPK39ZQA01 */ + publicId: string; + /** @enum {string} */ + status: "PENDING_PAYMENT" | "ABANDONED" | "PAYMENT_FAILED" | "PAYMENT_COMPLETED"; + customer: components["schemas"]["DevApiCartCustomerDto"]; + items: components["schemas"]["DevApiCartItemDto"][]; + totals: components["schemas"]["DevApiCartTotalsDto"]; + delivery?: components["schemas"]["DevApiCartDeliveryDto"] | null; + /** + * @description Developer-supplied metadata attached at cart creation. + * @example { + * "internalOrderId": "ORD-12345" + * } + */ + meta?: Record | null; + /** + * Format: date-time + * @example 2026-05-26T13:14:15.000Z + */ + createdAt: string; + /** + * Format: date-time + * @example 2026-05-26T13:14:15.000Z + */ + updatedAt: string; + }; + DevApiCheckoutPreviewResponseDto: { + /** @example 250000 */ + subtotal: number; + /** @example 1000 */ + deliveryCost: number; + /** @example 251000 */ + total: number; + /** + * @description Set only when paymentMethod = split_payment. + * @example 150000 + */ + onlineAmount?: number | null; + /** + * @description Set only when paymentMethod = split_payment. + * @example 101000 + */ + onDeliveryAmount?: number | null; + }; + DevApiCheckoutItemDto: { + /** @example 9023748120 */ + publicProductId: string; + /** @example 2 */ + quantity: number; + /** @example COMB_ABC123 */ + combinationPublicId?: string; + }; + DevApiCheckoutDeliveryDto: { + /** + * @example DELIVERY + * @enum {string} + */ + deliveryType: "DELIVERY" | "PICKUP"; + /** + * @description Required when deliveryType = DELIVERY. + * @example 1 + */ + deliveryAreaId?: number; }; DevApiCheckoutPreviewDto: { items: components["schemas"]["DevApiCheckoutItemDto"][]; delivery: components["schemas"]["DevApiCheckoutDeliveryDto"]; /** - * @description Modes de paiement actuellement exposés par la Developer API. * @example external_wallet * @enum {string} */ paymentMethod: "external_wallet" | "split_payment"; }; + DevApiCheckoutTotalsDto: { + /** @example 250000 */ + subtotal: number; + /** @example 1000 */ + deliveryCost: number; + /** @example 251000 */ + total: number; + /** @example 150000 */ + onlineAmount?: number | null; + /** @example 101000 */ + onDeliveryAmount?: number | null; + }; + DevApiCheckoutPaymentDto: { + /** @example PAY-XPK39ZQA01 */ + reference: string; + /** @example pending */ + status: string; + }; + DevApiCheckoutCreateResponseDto: { + /** @example CART-XPK39ZQA01 */ + publicId: string; + /** @example PENDING_PAYMENT */ + status: string; + totals: components["schemas"]["DevApiCheckoutTotalsDto"]; + payment: components["schemas"]["DevApiCheckoutPaymentDto"]; + /** @example https://checkout.moneroo.io/abc-def */ + checkoutUrl: string; + }; + DevApiCheckoutCustomerDto: { + /** @example Jean */ + firstName: string; + /** @example Kouassi */ + lastName: string; + /** @example jean@example.com */ + email: string; + /** @example +225 07 12 34 56 78 */ + phone: string; + }; DevApiCheckoutCreateDto: { customer: components["schemas"]["DevApiCheckoutCustomerDto"]; items: components["schemas"]["DevApiCheckoutItemDto"][]; @@ -392,15 +948,14 @@ export interface components { */ paymentMethod: "external_wallet" | "split_payment"; /** - * Format: uri - * @description URL HTTPS vers laquelle le client est redirigé après le checkout. Doit obligatoirement être en HTTPS. - * @example https://my-shop.com/after-checkout + * @description URL to redirect the customer to after the payment provider checkout. Must be HTTPS. + * @example https://my-app.com/after-checkout */ returnUrl: string; /** @example Appeler 30 min avant */ additionalDetails?: string; /** - * @description Charge JSON libre renvoyée telle quelle dans toutes les réponses panier / commande. Utilisez-la pour rattacher vos propres identifiants (ex. `internalOrderId`). + * @description Free-form JSON payload returned as-is in every cart/order response. Use it to attach your own identifiers (e.g. internalOrderId). * @example { * "internalOrderId": "ORD-12345", * "source": "mobile-app" @@ -408,275 +963,887 @@ export interface components { */ meta?: Record; }; + DevApiCheckoutRetryPayResponseDto: { + payment: components["schemas"]["DevApiCheckoutPaymentDto"]; + /** @example https://checkout.moneroo.io/abc-def */ + checkoutUrl: string; + }; DevApiCheckoutRetryPayDto: { + /** @example https://my-app.com/after-checkout */ + returnUrl: string; + }; + DevApiDeliveryAreaDto: { + /** + * @description Identifier to pass as `delivery.deliveryAreaId` when creating a cart. + * @example 1 + */ + id: number; + /** @example Cocody */ + name: string; /** - * Format: uri - * @example https://my-shop.com/after-checkout + * @description Delivery cost for this area. + * @example 1000 */ - returnUrl: string; + deliveryCost: number; }; - }; - responses: { - /** @description Clé API manquante ou invalide */ - Unauthorized: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; - }; + DevApiBusinessCategoryDto: { + /** @example 3 */ + id: number; + /** @example Restauration */ + name: string; }; - /** @description Requête invalide (validation du body ou de la query) */ - BadRequest: { - headers: { - [name: string]: unknown; - }; - content: { - /** - * @example { - * "success": false, - * "code": "BAD_REQUEST", - * "message": "La requête est invalide", - * "errors": { - * "items": [ - * "doit contenir au moins 1 élément" - * ] - * } - * } - */ - "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; - }; - }; - /** @description Ressource introuvable */ - NotFound: { - headers: { - [name: string]: unknown; - }; - content: { - /** - * @example { - * "success": false, - * "code": "NOT_FOUND", - * "message": "Ressource introuvable" - * } - */ - "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; - }; + DevApiMarketplaceProfileDto: { + /** @example ma-boutique */ + slug: string; + /** @example true */ + enabled: boolean; + businessCategory?: components["schemas"]["DevApiBusinessCategoryDto"] | null; + /** @example +225 07 12 34 56 78 */ + whatsappPhoneNumber?: string | null; + /** @example true */ + enablePayOnDelivery: boolean; + /** @example true */ + enableSplitPayment: boolean; + /** + * @description Default percentage paid online for split payment. Null if split payment is disabled. + * @example 30 + */ + defaultOnlineSplitPaymentPercentage?: number | null; + /** + * @description Whether the delivery cost is paid online or on delivery in a split payment. + * @example on_delivery + * @enum {string} + */ + splitPaymentDeliveryCostHandling: "online" | "on_delivery"; + /** + * Format: date-time + * @example 2026-05-26T13:14:15.000Z + */ + createdAt: string; + /** + * Format: date-time + * @example 2026-05-26T13:14:15.000Z + */ + updatedAt: string; }; - /** @description Produit introuvable */ - ProductNotFound: { - headers: { - [name: string]: unknown; - }; - content: { - /** - * @example { - * "success": false, - * "code": "PRODUCT_NOT_FOUND", - * "message": "Le produit n'a pas été trouvé" - * } - */ - "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; - }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export interface operations { + DevApiPingController_ping: { + parameters: { + query?: never; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; + }; + path?: never; + cookie?: never; }; - /** @description Panier introuvable */ - CartNotFound: { - headers: { - [name: string]: unknown; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"] & { + data?: components["schemas"]["PingPayload"]; + }; + }; }; - content: { - /** - * @example { - * "success": false, - * "code": "CART_NOT_FOUND", - * "message": "Le panier n'a pas été trouvé" - * } - */ - "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; }; }; - /** @description Le panier n'est plus dans un état autorisant un retry */ - CartNotRetryable: { - headers: { - [name: string]: unknown; + }; + ProductsDevApiController_list: { + parameters: { + query?: { + page?: number; + per_page?: number; + /** @description Column to sort by. */ + _sort?: "id" | "name" | "price" | "createdAt"; + /** @description Sort direction */ + _order?: "asc" | "desc"; + /** @description Full-text search on product name (min 3 characters). */ + search?: string; + /** @description Filter by collection slug. */ + collection?: string; + /** @description Include variations and combinations (SKUs) in the response. */ + includeVariations?: boolean; + /** @description Include disabled (draft) products. Defaults to false — only enabled products are returned. */ + includeDisabled?: boolean; }; - content: { - /** - * @example { - * "success": false, - * "code": "CART_NOT_RETRYABLE", - * "message": "Ce panier n'est plus en attente de paiement" - * } - */ - "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; }; + path?: never; + cookie?: never; }; - /** @description Une dépendance du checkout est introuvable (produit, combinaison ou zone de livraison) */ - CheckoutNotFound: { - headers: { - [name: string]: unknown; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiPaginatedEnvelopeDto"] & { + data?: components["schemas"]["DevApiProductDto"][]; + }; + }; }; - content: { - "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; }; }; - /** @description Stock insuffisant pour un ou plusieurs items */ - InsufficientStock: { - headers: { - [name: string]: unknown; + }; + ProductsDevApiController_getByPublicId: { + parameters: { + query: { + includeDisabled: string; }; - content: { - /** - * @example { - * "success": false, - * "code": "INSUFFICIENT_STOCK", - * "message": "Le stock est insuffisant", - * "errors": { - * "PRD-XPK39ZQA01": [ - * "stock disponible : 1, demandé : 2" - * ] - * } - * } - */ - "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; - }; - }; - /** @description Limite de débit dépassée. Consultez le header `Retry-After` (secondes). */ - RateLimited: { - headers: { - /** @description Nombre de secondes à attendre avant de réessayer. */ - "Retry-After"?: number; - /** @description Limite de la fenêtre courante. */ - "X-RateLimit-Limit"?: number; - /** @description Requêtes restantes dans la fenêtre. */ - "X-RateLimit-Remaining"?: number; - /** @description Timestamp Unix de réinitialisation de la fenêtre. */ - "X-RateLimit-Reset"?: number; - [name: string]: unknown; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; }; - content: { - /** - * @example { - * "success": false, - * "code": "RATE_LIMITED", - * "message": "Trop de requêtes, veuillez patienter" - * } - */ - "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + path: { + publicId: string; }; + cookie?: never; }; - /** @description Le provider de paiement n'a pas pu être joint. Le panier est conservé — relancez via `POST /v1/carts/{publicId}/pay`. */ - PaymentInitFailed: { - headers: { - [name: string]: unknown; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"] & { + data?: components["schemas"]["DevApiProductDto"]; + }; + }; }; - content: { - /** - * @example { - * "success": false, - * "code": "PAYMENT_INIT_FAILED", - * "message": "L'initialisation du paiement a échoué, réessayez via /pay", - * "data": { - * "cartPublicId": "CART-XPK39ZQA01" - * } - * } - */ - "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description The requested resource does not exist (`code: NOT_FOUND`). */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + }; + }; + ProductsDevApiController_getBySlug: { + parameters: { + query: { + includeDisabled: string; + }; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; + }; + path: { + slug: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"] & { + data?: components["schemas"]["DevApiProductDto"]; + }; + }; + }; + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description The requested resource does not exist (`code: NOT_FOUND`). */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; }; }; }; - parameters: { - /** @description Numéro de page (≥ 1). */ - Page: number; - /** @description Taille de page (bornée par la config plateforme, ~100 max). */ - PerPage: number; - /** @description Sens de tri. */ - Order: "asc" | "desc"; + CollectionsDevApiController_list: { + parameters: { + query?: { + page?: number; + per_page?: number; + /** @description Column to sort by. */ + _sort?: "id" | "name" | "createdAt"; + /** @description Sort direction */ + _order?: "asc" | "desc"; + /** @description Full-text search on collection name (min 3 characters). */ + search?: string; + }; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; + }; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiPaginatedEnvelopeDto"] & { + data?: components["schemas"]["DevApiCollectionDto"][]; + }; + }; + }; + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + }; }; - requestBodies: never; - headers: never; - pathItems: never; -} -export type $defs = Record; -export interface operations { - ping: { + CollectionsDevApiController_getByPublicId: { parameters: { query?: never; - header?: never; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; + }; + path: { + publicId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"] & { + data?: components["schemas"]["DevApiCollectionDto"]; + }; + }; + }; + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description The requested resource does not exist (`code: NOT_FOUND`). */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + }; + }; + CollectionsDevApiController_getBySlug: { + parameters: { + query?: never; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; + }; + path: { + slug: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"] & { + data?: components["schemas"]["DevApiCollectionDto"]; + }; + }; + }; + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description The requested resource does not exist (`code: NOT_FOUND`). */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + }; + }; + OrdersDevApiController_list: { + parameters: { + query?: { + page?: number; + per_page?: number; + /** @description Column to sort by. */ + _sort?: "id" | "createdAt" | "amount"; + /** @description Sort direction */ + _order?: "asc" | "desc"; + /** @description Full-text search on order publicId, payment reference or customer info. */ + search?: string; + }; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; + }; path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Clé valide */ 200: { headers: { [name: string]: unknown; }; content: { - /** - * @example { - * "success": true, - * "data": { - * "marketplaceId": 42, - * "timestamp": "2026-05-28T10:15:00.000Z" - * } - * } - */ - "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"]; + "application/json": components["schemas"]["DevApiPaginatedEnvelopeDto"] & { + data?: components["schemas"]["DevApiOrderListItemDto"][]; + }; + }; + }; + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + }; + }; + OrdersDevApiController_getByPublicId: { + parameters: { + query?: never; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; + }; + path: { + publicId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"] & { + data?: components["schemas"]["DevApiOrderDetailDto"]; + }; + }; + }; + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description The requested resource does not exist (`code: NOT_FOUND`). */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + }; + }; + OrdersDevApiController_getInvoice: { + parameters: { + query?: never; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; + }; + path: { + publicId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description The requested resource does not exist (`code: NOT_FOUND`). */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + }; + }; + CartsDevApiController_list: { + parameters: { + query?: { + page?: number; + per_page?: number; + /** @description Column to sort by. */ + _sort?: "id" | "createdAt"; + /** @description Sort direction */ + _order?: "asc" | "desc"; + /** @description Full-text search on cart publicId or customer info. */ + search?: string; + }; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; + }; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiPaginatedEnvelopeDto"] & { + data?: components["schemas"]["DevApiCartListItemDto"][]; + }; + }; + }; + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + }; + }; + CheckoutDevApiController_create: { + parameters: { + query?: never; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; + }; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DevApiCheckoutCreateDto"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"] & { + data?: components["schemas"]["DevApiCheckoutCreateResponseDto"]; + }; + }; + }; + /** @description Invalid request — malformed parameters or body (`code: BAD_REQUEST`). */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description The requested resource does not exist (`code: NOT_FOUND`). */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description The request is well-formed but cannot be processed (`code: UNPROCESSABLE_ENTITY`). */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; }; }; - 401: components["responses"]["Unauthorized"]; - 429: components["responses"]["RateLimited"]; - }; - }; - listProducts: { - parameters: { - query?: { - /** @description Numéro de page (≥ 1). */ - page?: components["parameters"]["Page"]; - /** @description Taille de page (bornée par la config plateforme, ~100 max). */ - per_page?: components["parameters"]["PerPage"]; - /** @description Colonne de tri. */ - _sort?: "id" | "name" | "price" | "createdAt"; - /** @description Sens de tri. */ - _order?: components["parameters"]["Order"]; - /** @description Recherche plein-texte sur le nom du produit (3 caractères minimum). */ - search?: string; - /** @description Filtrer par slug de collection. */ - collection?: string; - /** @description Inclure les variations et combinaisons (SKU) dans la réponse. */ - includeVariations?: boolean; - /** @description Inclure les produits désactivés (brouillons). Par défaut, seuls les produits activés sont retournés. */ - includeDisabled?: boolean; + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Liste paginée de produits */ - 200: { + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description The payment provider could not be reached (`code: PAYMENT_INIT_FAILED`). `data.cartPublicId` carries the created cart so the payment can be retried. */ + 502: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DevApiPaginatedEnvelopeDto"]; + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; }; }; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 429: components["responses"]["RateLimited"]; }; }; - getProductByPublicId: { + CartsDevApiController_getByPublicId: { parameters: { - query?: { - /** @description Permet de résoudre un produit désactivé (brouillon). */ - includeDisabled?: boolean; + query?: never; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; }; - header?: never; path: { publicId: string; }; @@ -684,363 +1851,349 @@ export interface operations { }; requestBody?: never; responses: { - /** @description Produit trouvé */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"]; + "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"] & { + data?: components["schemas"]["DevApiCartDetailDto"]; + }; }; }; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["ProductNotFound"]; - 429: components["responses"]["RateLimited"]; - }; - }; - getProductBySlug: { - parameters: { - query?: { - /** @description Permet de résoudre un produit désactivé (brouillon). */ - includeDisabled?: boolean; + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; }; - header?: never; - path: { - slug: string; + /** @description The requested resource does not exist (`code: NOT_FOUND`). */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Produit trouvé */ - 200: { + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"]; + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; }; }; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["ProductNotFound"]; - 429: components["responses"]["RateLimited"]; }; }; - listCollections: { + CheckoutDevApiController_preview: { parameters: { - query?: { - /** @description Numéro de page (≥ 1). */ - page?: components["parameters"]["Page"]; - /** @description Taille de page (bornée par la config plateforme, ~100 max). */ - per_page?: components["parameters"]["PerPage"]; - /** @description Colonne de tri. */ - _sort?: "id" | "name" | "createdAt"; - /** @description Sens de tri. */ - _order?: components["parameters"]["Order"]; - /** @description Recherche plein-texte sur le nom de la collection (3 caractères minimum). */ - search?: string; + query?: never; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; }; - header?: never; path?: never; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["DevApiCheckoutPreviewDto"]; + }; + }; responses: { - /** @description Liste paginée de collections */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DevApiPaginatedEnvelopeDto"]; + "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"] & { + data?: components["schemas"]["DevApiCheckoutPreviewResponseDto"]; + }; }; }; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 429: components["responses"]["RateLimited"]; - }; - }; - getCollectionByPublicId: { - parameters: { - query?: never; - header?: never; - path: { - publicId: string; + /** @description Invalid request — malformed parameters or body (`code: BAD_REQUEST`). */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Collection trouvée */ - 200: { + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"]; + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; }; }; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 429: components["responses"]["RateLimited"]; - }; - }; - getCollectionBySlug: { - parameters: { - query?: never; - header?: never; - path: { - slug: string; + /** @description The requested resource does not exist (`code: NOT_FOUND`). */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Collection trouvée */ - 200: { + /** @description The request is well-formed but cannot be processed (`code: UNPROCESSABLE_ENTITY`). */ + 422: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"]; + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; }; }; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 429: components["responses"]["RateLimited"]; - }; - }; - listOrders: { - parameters: { - query?: { - /** @description Numéro de page (≥ 1). */ - page?: components["parameters"]["Page"]; - /** @description Taille de page (bornée par la config plateforme, ~100 max). */ - per_page?: components["parameters"]["PerPage"]; - /** @description Colonne de tri. */ - _sort?: "id" | "createdAt" | "amount"; - /** @description Sens de tri. */ - _order?: components["parameters"]["Order"]; - /** @description Recherche plein-texte sur le `publicId` de commande, la référence de paiement ou les infos client. */ - search?: string; + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Liste paginée de commandes */ - 200: { + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DevApiPaginatedEnvelopeDto"]; + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; }; }; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 429: components["responses"]["RateLimited"]; }; }; - getOrderByPublicId: { + CheckoutDevApiController_retryPay: { parameters: { query?: never; - header?: never; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; + }; path: { publicId: string; }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["DevApiCheckoutRetryPayDto"]; + }; + }; responses: { - /** @description Commande trouvée */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"]; + "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"] & { + data?: components["schemas"]["DevApiCheckoutRetryPayResponseDto"]; + }; }; }; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 429: components["responses"]["RateLimited"]; - }; - }; - getOrderInvoice: { - parameters: { - query?: never; - header?: never; - path: { - publicId: string; + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Flux PDF de la facture */ - 200: { + /** @description The requested resource does not exist (`code: NOT_FOUND`). */ + 404: { headers: { [name: string]: unknown; }; content: { - "application/pdf": string; + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; }; }; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 429: components["responses"]["RateLimited"]; - }; - }; - listCarts: { - parameters: { - query?: { - /** @description Numéro de page (≥ 1). */ - page?: components["parameters"]["Page"]; - /** @description Taille de page (bornée par la config plateforme, ~100 max). */ - per_page?: components["parameters"]["PerPage"]; - /** @description Colonne de tri. */ - _sort?: "id" | "createdAt"; - /** @description Sens de tri. */ - _order?: components["parameters"]["Order"]; - /** @description Recherche plein-texte sur le `publicId` de panier ou les infos client. */ - search?: string; + /** @description The request is well-formed but cannot be processed (`code: UNPROCESSABLE_ENTITY`). */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Liste paginée de paniers */ - 200: { + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DevApiPaginatedEnvelopeDto"]; + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; }; }; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 429: components["responses"]["RateLimited"]; - }; - }; - createCart: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["DevApiCheckoutCreateDto"]; + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; }; - }; - responses: { - /** @description Panier créé, URL de checkout dans `data.checkoutUrl` */ - 201: { + /** @description The payment provider could not be reached (`code: PAYMENT_INIT_FAILED`). `data.cartPublicId` carries the created cart so the payment can be retried. */ + 502: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"]; + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; }; }; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["CheckoutNotFound"]; - 422: components["responses"]["InsufficientStock"]; - 429: components["responses"]["RateLimited"]; - 502: components["responses"]["PaymentInitFailed"]; }; }; - getCartByPublicId: { + DeliveryAreasDevApiController_list: { parameters: { query?: never; - header?: never; - path: { - publicId: string; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; }; + path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Panier trouvé */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"]; + "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"] & { + data?: components["schemas"]["DevApiDeliveryAreaDto"][]; + }; + }; + }; + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; }; }; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["CartNotFound"]; - 429: components["responses"]["RateLimited"]; }; }; - previewCart: { + MarketplaceDevApiController_getProfile: { parameters: { query?: never; - header?: never; + header: { + /** @description Developer API key (Bearer xdk_…) */ + Authorization: string; + }; path?: never; cookie?: never; }; - requestBody: { - content: { - "application/json": components["schemas"]["DevApiCheckoutPreviewDto"]; - }; - }; + requestBody?: never; responses: { - /** @description Totaux calculés */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"]; + "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"] & { + data?: components["schemas"]["DevApiMarketplaceProfileDto"]; + }; }; }; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["CheckoutNotFound"]; - 422: components["responses"]["InsufficientStock"]; - 429: components["responses"]["RateLimited"]; - }; - }; - retryCartPayment: { - parameters: { - query?: never; - header?: never; - path: { - publicId: string; + /** + * @description Missing or invalid developer API key + * + * Missing or invalid API key (`code: UNAUTHORIZED`). + */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["DevApiCheckoutRetryPayDto"]; + /** @description The requested resource does not exist (`code: NOT_FOUND`). */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; }; - }; - responses: { - /** @description Nouvelle URL de checkout dans `data.checkoutUrl` */ - 200: { + /** @description Rate limit exceeded on the burst or sustained window (`code: TOO_MANY_REQUESTS`). */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; + }; + }; + /** @description Unexpected server error (`code: INTERNAL_SERVER_ERROR`). */ + 500: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DevApiSuccessEnvelopeDto"]; + "application/json": components["schemas"]["DevApiErrorEnvelopeDto"]; }; }; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["CartNotFound"]; - 409: components["responses"]["CartNotRetryable"]; - 429: components["responses"]["RateLimited"]; - 502: components["responses"]["PaymentInitFailed"]; }; }; } diff --git a/src/types/public.ts b/src/types/public.ts index f9eeee7..9577d0c 100644 --- a/src/types/public.ts +++ b/src/types/public.ts @@ -1,48 +1,132 @@ /** - * Public, hand-written type surface for the Xedo SDK. + * Public type surface for the Xedo SDK. * * The Xedo Developer API returns its resource payloads inside a generic - * envelope (`{ success, data }`). The entity payloads themselves are described - * loosely in `openapi.json` (`type: object`), so we expose them as open - * JSON objects here and keep the precise, validated shapes for the checkout - * inputs — which the API does constrain. The generated mirror of the spec - * lives in `./generated.ts` (do not edit by hand). + * envelope (`{ success, data }`). Since the API v1 spec now describes every + * entity in detail, these public types are derived directly from the generated + * mirror of `openapi.json` (`./generated.ts`, do not edit by hand) so they stay + * in sync on every `npm run generate`. Only cross-cutting helpers (pagination, + * list params, rate-limit) are hand-written here. */ -/** A free-form JSON object returned by the API. */ +import type { components } from './generated'; + +type Schemas = components['schemas']; + +/** A free-form JSON object (e.g. the developer-supplied `meta` payload). */ export type JsonObject = { [key: string]: unknown }; +/** + * `meta` is a free-form JSON object, but openapi-typescript renders the spec's + * loose `object` as `Record`. Swap it back to {@link JsonObject}. + */ +type WithMeta = Omit & { meta?: JsonObject | null }; + /** Sort direction shared by every paginated list endpoint. */ export type SortOrder = 'asc' | 'desc'; -/** Result of `GET /v1/ping` — use it to validate an API key end to end. */ -export interface PingResult { - marketplaceId: number; - timestamp: string; -} +// --- Enums (single source: the generated spec) ------------------------------- + +/** Lifecycle status of an order. */ +export type OrderStatus = Schemas['DevApiOrderDetailDto']['status']; +/** Lifecycle status of a cart (orders that are not yet paid). */ +export type CartStatus = Schemas['DevApiCartDetailDto']['status']; +/** Fulfillment status once an order is being prepared/shipped. */ +export type FulfillmentStatus = Schemas['DevApiOrderDeliveryDto']['orderStatus']; +/** Delivery mode of a cart/order. */ +export type DeliveryType = Schemas['DevApiOrderDeliveryDto']['deliveryType']; +/** Payment status of an order. */ +export type PaymentStatus = Schemas['DevApiOrderPaymentDto']['status']; +/** Payment method as reported on a paid order (read side). */ +export type OrderPaymentMethod = Schemas['DevApiOrderPaymentDto']['method']; +/** How a per-option/combination price is adjusted. */ +export type PriceAdjustmentType = NonNullable; +/** Gallery media kind. */ +export type MediaType = Schemas['DevApiProductGalleryMediaDto']['type']; + +// --- Entities ---------------------------------------------------------------- +/** Result of `GET /v1/ping` — use it to validate an API key end to end. */ +export type PingResult = Schemas['PingPayload']; + +/** The lightweight collection reference embedded on a product. */ +export type ProductCollection = Schemas['DevApiProductCollectionDto']; +/** A gallery image or video attached to a product/variation option. */ +export type ProductGalleryMedia = Schemas['DevApiProductGalleryMediaDto']; +/** One selectable option (e.g. "XL") of a product variation. */ +export type ProductVariationOption = Schemas['DevApiProductVariationOptionDto']; +/** A product variation axis (e.g. "Size") and its options. */ +export type ProductVariation = Schemas['DevApiProductVariationDto']; +/** A combination (SKU) with its own stock and pricing. */ +export type ProductCombination = Schemas['DevApiProductCombinationDto']; /** A product from the merchant catalogue (`GET /v1/products`). */ -export type Product = JsonObject; +export type Product = Schemas['DevApiProductDto']; /** A collection / category of products (`GET /v1/collections`). */ -export type Collection = JsonObject; - -/** A paid order (`GET /v1/orders`). */ -export type Order = JsonObject; - -/** A cart (`GET /v1/carts`). `DRAFT` carts are never exposed by the API. */ -export type Cart = JsonObject; +export type Collection = Schemas['DevApiCollectionDto']; + +/** Customer details attached to an order. */ +export type OrderCustomer = Schemas['DevApiOrderCustomerDto']; +/** Payment details of a paid order. */ +export type OrderPayment = Schemas['DevApiOrderPaymentDto']; +/** A single line item of an order. */ +export type OrderItem = Schemas['DevApiOrderItemDto']; +/** Computed monetary totals of an order. */ +export type OrderTotals = Schemas['DevApiOrderTotalsDto']; +/** Delivery information of an order. */ +export type OrderDelivery = Schemas['DevApiOrderDeliveryDto']; +/** A row in `GET /v1/orders` (summary). */ +export type OrderListItem = WithMeta; +/** A full order from `GET /v1/orders/{publicId}`. */ +export type Order = WithMeta; + +/** Customer details attached to a cart. */ +export type CartCustomer = Schemas['DevApiCartCustomerDto']; +/** A single line item of a cart. */ +export type CartItem = Schemas['DevApiCartItemDto']; +/** Computed monetary totals of a cart. */ +export type CartTotals = Schemas['DevApiCartTotalsDto']; +/** Delivery information of a cart. */ +export type CartDelivery = Schemas['DevApiCartDeliveryDto']; +/** A row in `GET /v1/carts` (summary). `DRAFT` carts are never exposed. */ +export type CartListItem = WithMeta; +/** A full cart from `GET /v1/carts/{publicId}`. `DRAFT` carts are never exposed. */ +export type Cart = WithMeta; /** Computed totals returned by `POST /v1/carts/preview` (nothing persisted). */ -export type CheckoutPreview = JsonObject; - +export type CheckoutPreview = Schemas['DevApiCheckoutPreviewResponseDto']; +/** Totals carried on a created cart. */ +export type CheckoutTotals = Schemas['DevApiCheckoutTotalsDto']; +/** Payment handle carried on a created cart. */ +export type CheckoutPayment = Schemas['DevApiCheckoutPaymentDto']; /** - * Returned by `POST /v1/carts` and `POST /v1/carts/{publicId}/pay`. Always - * carries the hosted `checkoutUrl` to redirect the customer to. + * Returned by `POST /v1/carts`. Always carries the hosted `checkoutUrl` to + * redirect the customer to. */ -export interface CheckoutResult extends JsonObject { - checkoutUrl: string; -} +export type CheckoutResult = Schemas['DevApiCheckoutCreateResponseDto']; +/** Returned by `POST /v1/carts/{publicId}/pay`. */ +export type CheckoutRetryResult = Schemas['DevApiCheckoutRetryPayResponseDto']; + +/** A delivery area (`GET /v1/delivery-areas`). */ +export type DeliveryArea = Schemas['DevApiDeliveryAreaDto']; + +/** The merchant's business category. */ +export type BusinessCategory = Schemas['DevApiBusinessCategoryDto']; +/** The marketplace profile (`GET /v1/marketplace`). */ +export type MarketplaceProfile = Schemas['DevApiMarketplaceProfileDto']; + +// --- Checkout inputs --------------------------------------------------------- + +export type CheckoutItem = Schemas['DevApiCheckoutItemDto']; +export type CheckoutDelivery = Schemas['DevApiCheckoutDeliveryDto']; +export type CheckoutCustomer = Schemas['DevApiCheckoutCustomerDto']; +/** Payment method accepted when creating a cart (write side). */ +export type PaymentMethod = Schemas['DevApiCheckoutCreateDto']['paymentMethod']; +export type CheckoutPreviewInput = Schemas['DevApiCheckoutPreviewDto']; +export type CheckoutCreateInput = WithMeta; +export type CheckoutRetryPayInput = Schemas['DevApiCheckoutRetryPayDto']; + +// --- Hand-written cross-cutting helpers -------------------------------------- /** Shared cursor parameters for every paginated list endpoint. */ export interface ListParams { @@ -112,52 +196,3 @@ export interface RateLimitInfo { remaining: number | null; reset: number | null; } - -// --- Checkout inputs (precisely typed from openapi.json) --------------------- - -export interface CheckoutItem { - /** e.g. "PRD-XPK39ZQA01". */ - publicProductId: string; - /** Quantity, >= 1. */ - quantity: number; - /** SKU public id, when the product has variations. */ - combinationPublicId?: string; -} - -export interface CheckoutDelivery { - deliveryType: 'DELIVERY' | 'PICKUP'; - /** Required when `deliveryType === 'DELIVERY'`. */ - deliveryAreaId?: number; -} - -export interface CheckoutCustomer { - firstName: string; - lastName: string; - email: string; - phone: string; -} - -export type PaymentMethod = 'external_wallet' | 'split_payment'; - -export interface CheckoutPreviewInput { - items: CheckoutItem[]; - delivery: CheckoutDelivery; - paymentMethod: PaymentMethod; -} - -export interface CheckoutCreateInput extends CheckoutPreviewInput { - customer: CheckoutCustomer; - /** HTTPS is mandatory. */ - returnUrl: string; - additionalDetails?: string; - /** - * Free JSON payload echoed back, unchanged, in every cart/order response. - * Use it to correlate a Xedo order with your own state (`internalOrderId`, - * `source`, `templateId`, …). - */ - meta?: Record; -} - -export interface CheckoutRetryPayInput { - returnUrl: string; -} diff --git a/test/resources.test.ts b/test/resources.test.ts index 3ea2759..a329294 100644 --- a/test/resources.test.ts +++ b/test/resources.test.ts @@ -67,6 +67,45 @@ describe('list endpoints', () => { }); }); +describe('deliveryAreas.list', () => { + it('returns the unwrapped array of delivery areas', async () => { + server.use( + http.get(`${BASE}/v1/delivery-areas`, () => + ok([ + { id: 1, name: 'Cocody', deliveryCost: 1000 }, + { id: 2, name: 'Plateau', deliveryCost: 1500 }, + ]), + ), + ); + + const xedo = makeClient(); + const areas = await xedo.deliveryAreas.list(); + + expect(areas).toEqual([ + { id: 1, name: 'Cocody', deliveryCost: 1000 }, + { id: 2, name: 'Plateau', deliveryCost: 1500 }, + ]); + }); +}); + +describe('marketplace.retrieve', () => { + it('returns the unwrapped marketplace profile', async () => { + const profile = { + slug: 'ma-boutique', + enabled: true, + enablePayOnDelivery: true, + enableSplitPayment: true, + splitPaymentDeliveryCostHandling: 'on_delivery', + createdAt: '2026-05-26T13:14:15.000Z', + updatedAt: '2026-05-26T13:14:15.000Z', + }; + server.use(http.get(`${BASE}/v1/marketplace`, () => ok(profile))); + + const xedo = makeClient(); + expect(await xedo.marketplace.retrieve()).toEqual(profile); + }); +}); + describe('orders.invoice', () => { it('returns the PDF as an ArrayBuffer', async () => { const pdf = new Uint8Array([0x25, 0x50, 0x44, 0x46]); // %PDF