API Sylvinio — Documentation
Référence technique de l'API REST publique. Connectez votre boutique à Zapier, à un site PrestaShop / Shopify, à votre ERP ou à toute autre intégration tierce.
Démarrage rapide
- Activez l'API publique dans votre plan (option
publicApi). - Générez une clé depuis Compte → Clés API (label, scopes nécessaires).
- Copiez la clé affichée (visible une seule fois) puis testez :
curl https://app.sylvinio.com/api/v1/me \
-H "Authorization: Bearer sylv_live_xxxxxxxx_<secret>"Réponse :
{
"shop": { "id": "...", "name": "Ma Boutique", "slug": "ma-boutique" },
"apiKey": { "label": "Zapier prod", "scopes": ["products:read", "orders:read"] }
}Authentification
Toutes les requêtes doivent inclure un header Authorization: Bearer <clé>. Les clés ont le format :
sylv_live_<8-hex-prefix>_<64-hex-secret>Le préfixe sylv_live_xxxxxxxxest visible dans votre dashboard ; le suffixe (32 octets aléatoires) n'est jamais réaffiché — sauvegardez-le dans votre coffre. En cas de fuite, révoquez la clé et créez-en une nouvelle.
Une clé révoquée ou expirée renvoie 401 UNAUTHORIZED. Une clé d'une boutique dont l'abonnement n'est pas actif renvoie 403 SUBSCRIPTION_INACTIVE. Si la feature publicApi n'est pas dans le plan, c'est 403 FEATURE_NOT_IN_PLAN.
Scopes
Chaque clé porte une liste de scopes. Donnez le minimum nécessaire à votre intégration : si Zapier n'a besoin que de lire les commandes, ne lui donnez pas clients:read. Vous pouvez créer plusieurs clés avec des scopes différents pour isoler vos intégrations.
| Scope | Description |
|---|---|
products:read | Lire les produits, leurs variantes et leur stock affiché. |
products:write | Réservé V2. |
orders:read | Lire les commandes (POS + Click & Collect + en ligne). |
orders:write | Réservé V2. |
stock:read | Lire l'état du stock par variante. |
stock:write | Ajuster le stock (POST /stock/adjustments). |
clients:read | Lire les clients identifiés et leurs coordonnées. |
clients:write | Réservé V2. |
loyalty:read | Lire les soldes fidélité, paliers, tickets loterie. |
loyalty:write | Réservé V2. |
Les scopes en écriture (:write) hors stock:writesont réservés pour la V2. La V1 est volontairement majoritairement lecture pour limiter la surface d'attaque.
Pagination
Les endpoints de liste utilisent un curseur opaque. Réponse type :
{
"data": [ /* items */ ],
"pageInfo": {
"hasMore": true,
"nextCursor": "cmo93tkdb00971okloesfihdj",
"limit": 20
}
}Pour récupérer la page suivante, passez ?cursor=<nextCursor>. Le curseur est stable tant que les ids ne sont pas réorganisés. Limite max : 100.
Format des prix
Tous les montants monétaires sont retournés en centimes (Int) avec un suffixe Cents. Exemple : "priceCents": 1990 = 19,90 €.
Avantage : pas d'arrondi flottant côté client. Pour afficher, divisez par 100 et formatez avec votre devise. Le taux de TVA est exposé en string (préservation Decimal) : "taxRate": "20.00".
Erreurs
Toutes les erreurs renvoient ce format :
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid query parameters",
"details": [/* zod issues éventuels */]
}
}| Status | Code | Quand |
|---|---|---|
| 400 | VALIDATION_ERROR | Body ou query invalide |
| 400 | INVALID_JSON | Body JSON malformé |
| 401 | UNAUTHORIZED | Header manquant, clé invalide / révoquée / expirée |
| 403 | INSUFFICIENT_SCOPE | Clé valide mais sans le scope requis |
| 403 | FEATURE_NOT_IN_PLAN | L'API publique n'est pas dans le plan |
| 403 | SUBSCRIPTION_INACTIVE | Abonnement expiré ou annulé |
| 404 | NOT_FOUND | Ressource inconnue (ou d'une autre boutique) |
| 422 | STOCK_NOT_TRACKED | Suivi de stock désactivé pour cette variante |
| 429 | RATE_LIMITED | Trop de requêtes — voir header Retry-After |
| 500 | INTERNAL_ERROR | Erreur serveur inattendue |
Rate limiting
Limites par clé, fenêtre glissante :
- Lecture (
GET) : 120 requêtes / minute - Écriture (
POST/PUT/DELETE) : 30 requêtes / minute
Quand vous dépassez, vous recevez 429 RATE_LIMITED avec un header Retry-After: <secondes>. Implémentez un back-off exponentiel côté client.
GET /me
Endpoint d'introspection : retourne les infos de la clé. N'exige aucun scope spécifique.
/api/v1/meScope : anycurl /api/v1/me -H "Authorization: Bearer <key>"{
"shop": { "id": "...", "name": "Ma Boutique", "slug": "ma-boutique" },
"apiKey": { "label": "Zapier prod", "scopes": ["products:read", "orders:read"] }
}Produits
/api/v1/productsScope : products:readListe paginée des produits actifs.
Query params : cursor, limit (1-100, défaut 20), q (recherche nom/EAN/SKU/réf), category, brand, productType, active (true|false|all), updatedSince (ISO 8601).
curl "/api/v1/products?limit=20&q=pod" \
-H "Authorization: Bearer <key>"{
"data": [{
"id": "cmo93twzf...",
"name": "Pod XROS 4",
"productType": "Pod",
"ean": "6970310300042",
"sku": "VAP-001",
"priceCents": 2990,
"listPriceCents": 2990,
"compareAtPriceCents": null,
"promoActive": false,
"taxRate": "20.00",
"active": true,
"trackStock": true,
"stockQuantity": null,
"tags": ["nouveau"],
"photos": ["https://cdn.sylvinio.com/products/xxx.webp"],
"category": { "id": "...", "name": "Pods" },
"brand": { "id": "...", "name": "Vaporesso" },
"variants": [{
"id": "...",
"label": "Black",
"sku": "VAP-001-BLK",
"barcode": "6970310300042",
"swatchColor": "#000000",
"priceCents": 2990,
"stock": 12,
"lowStockThreshold": 5,
"isDefault": true,
"active": true,
"order": 0
}],
"createdAt": "...",
"updatedAt": "..."
}],
"pageInfo": { "hasMore": true, "nextCursor": "...", "limit": 20 }
}/api/v1/products/:idScope : products:readDétail d'un produit. Inclut les variantes même inactives (la liste les filtre par défaut).
Commandes
Champs volontairement exclus pour conformité NF525 et confidentialité : signature, previousSignature, cumulativeTotalTTCSnapshot, stripePaymentIntentId, internalNote.
/api/v1/ordersScope : orders:readQuery params : cursor, limit, status (pending|preparing|ready|completed|cancelled), paymentStatus (pending|paid|refunded), source (pos|click-collect|online), clientId, dateFrom, dateTo.
{
"data": [{
"id": "...",
"orderNumber": 42,
"source": "pos",
"status": "completed",
"paymentStatus": "paid",
"subtotalCents": 4990,
"discountAmountCents": 0,
"taxAmountCents": 998,
"totalCents": 4990,
"paymentMethod": "card",
"paidAt": "2026-04-30T16:01:19.358Z",
"customer": null,
"clientId": null,
"items": [{
"id": "...",
"productId": "...",
"variantId": "...",
"productName": "Pod XROS 4",
"unitPriceCents": 2990,
"quantity": 1,
"totalCents": 2990,
"taxRate": "20.00",
"taxAmountCents": 598,
"refunded": null
}],
"createdAt": "...",
"updatedAt": "..."
}]
}/api/v1/orders/:idScope : orders:readDétail commande avec lignes complètes.
Stock
/api/v1/stockScope : stock:readQuery params : cursor, limit (défaut 50), productId, q (EAN/SKU/nom), lowStockOnly=true, trackedOnly=false (défaut true, masque les variantes sans suivi).
{
"data": [{
"variantId": "...",
"productId": "...",
"productName": "Pod XROS 4",
"variantLabel": "Black",
"sku": "VAP-001-BLK",
"barcode": "6970310300042",
"tracked": true,
"stock": 12,
"lowStockThreshold": 5,
"isLowStock": false,
"isOutOfStock": false,
"active": true
}]
}/api/v1/stock/adjustmentsScope : stock:writeAjuste le stock d'une variante par delta. Crée un StockMovement traçable horodaté.
curl -X POST /api/v1/stock/adjustments \
-H "Authorization: Bearer <key>" \
-H "Content-Type: application/json" \
-d '{ "variantId": "...", "quantity": -2, "reason": "Casse en boutique" }'{
"data": {
"variantId": "...",
"productId": "...",
"previousStock": 10,
"newStock": 8,
"delta": -2,
"movementId": "...",
"appliedAt": "2026-05-01T17:11:23.844Z"
}
}Erreurs spécifiques : 404 si la variante est inconnue ou appartient à une autre boutique. 422 STOCK_NOT_TRACKEDsi le suivi de stock n'est pas activé pour cette variante (à activer dans le dashboard d'abord).
Clients & fidélité
Champs exclus de la sortie : note (note privée gérant), anonymousClientId (lien legacy).
/api/v1/clientsScope : clients:readQuery params : cursor, limit, q (recherche nom/téléphone/email).
{
"data": [{
"id": "...",
"name": "Marie Dupont",
"displayName": null,
"phone": "0612345678",
"email": "[email protected]",
"billing": {
"company": null,
"vatNumber": null,
"address": null,
"city": null,
"postalCode": null,
"country": "FR"
},
"birthDate": null,
"loyalty": {
"points": 2082,
"expiresAt": null,
"pointsLifetime": 1217,
"pointsAllTime": 2082,
"tierAchievedAt": "2026-04-27T11:14:23.433Z"
},
"receiptByEmail": false,
"tags": [],
"createdAt": "...",
"updatedAt": "..."
}]
}/api/v1/clients/:idScope : clients:readDétail d'un client.
/api/v1/clients/:id/loyaltyScope : loyalty:readSolde fidélité, palier courant + suivant + progression, 10 derniers tickets loterie, 10 derniers spins instantanés.
{
"data": {
"clientId": "...",
"points": 2082,
"pointsLifetime": 1217,
"pointsAllTime": 2082,
"tier": {
"current": { "id": "silver", "name": "Silver", "minPointsLifetime": 500, "color": "#9CA3AF", "achievedAt": "..." },
"next": { "id": "gold", "name": "Gold", "minPointsLifetime": 1500, "pointsToNext": 283 },
"progress": 0.717
},
"recentLotteryTickets": [{ "id": "...", "orderId": "...", "createdAt": "..." }],
"recentSpins": [{ "id": "...", "orderId": "...", "won": true, "prizeLabel": "Pod offert", "prizeType": "free_product", "createdAt": "..." }]
}
}Besoin d'aide ou d'un endpoint manquant ?
L'API est en V1 — la V2 ouvrira l'écriture sur produits / clients / fidélité et ajoutera les webhooks. Si vous avez un cas d'usage qui n'est pas couvert, signalez-le via le programme Éclaireur ou le chat support.