API de dropshipping
À qui s’adresse ce contenu
Section intitulée « À qui s’adresse ce contenu »Pour les développeurs qui automatisent une boutique qu’ils possèdent ou gèrent, via l’API REST, les SDK Posty5 ou n8n. Les acheteurs et les fournisseurs n’appellent jamais ces routes. Si vous gérez la boutique manuellement, le guide du marchand est la page qu’il vous faut. Ouvrir le guide du marchand
Authentification
Section intitulée « Authentification »Chaque requête transporte votre clé API dans cet en-tête —
X-API-Key: YOUR_API_KEYCréez une clé dans le tableau de bord Posty5, dans les paramètres du compte, sous Clés API. Les clés API sont disponibles pour les comptes Développeur.
Chaque route ci-dessous agit sur une boutique et vérifie l’autorisation de boutique indiquée à côté. Le propriétaire de la clé doit posséder la boutique ou faire partie de son équipe avec cette autorisation.
Lorsque le forfait du propriétaire de la boutique n’inclut pas le dropshipping (Pro ou supérieur), ces routes sont refusées , connecter un fournisseur (avec une clé API ou en se connectant), remplacer ses identifiants, activer une connexion, modifier son automatisation, parcourir les produits d’un fournisseur, récupérer un produit de fournisseur, résoudre l’URL d’un produit, prévisualiser ou exécuter une importation, créer un lien produit, et envoyer, réessayer ou payer une commande fournisseur. C’est le forfait du propriétaire qui décide, et non celui du membre de l’équipe qui effectue l’appel. Tout le reste reste ouvert sur n’importe quel forfait, de sorte qu’une boutique passant sous le seuil Pro peut toujours lire ce qu’elle a, désactiver une connexion, modifier ses paramètres, la tester ou la déconnecter, modifier, synchroniser ou supprimer des liens de produits, et annuler une commande fournisseur ou l’exécuter manuellement.
URL de base
Section intitulée « URL de base »- dropshipping.developer.base.hostAt
- dropshipping.developer.base.prefixIs
- dropshipping.developer.base.docsAt
Les chemins ci-dessous sont relatifs au préfixe du fournisseur. Le premier paramètre est toujours l’identifiant de la boutique, et l’identifiant suivant est la connexion du fournisseur.
Connexions
Section intitulée « Connexions »| Méthode | Route | Autorisation | Fonction |
|---|---|---|---|
GET | /:storeId/catalogue | suppliers.view | Les fournisseurs que cette boutique peut connecter, avec ce que chacun peut faire. |
GET | /:storeId | suppliers.view | Connexions des fournisseurs de la boutique, avec état de santé et automatisation. Les identifiants ne sont jamais renvoyés. |
POST | /:storeId | suppliers.manage | Connecter un fournisseur avec sa clé API. La clé est vérifiée auprès du fournisseur avant d’être enregistrée. |
POST | /:storeId/oauth/start | suppliers.manage | Commencer à connecter un fournisseur qui utilise la connexion, comme AliExpress. Renvoie l’adresse vers laquelle le marchand sera redirigé. |
PUT | /:storeId/:id | suppliers.manage | Remplacer les identifiants de la connexion. |
POST | /:storeId/:id/test | suppliers.manage | Vérifier la connexion maintenant et enregistrer son état de santé. |
GET | /:storeId/:id/balance | suppliers.view | Le solde du compte chez le fournisseur, lorsque le fournisseur en signale un. |
GET | /:storeId/:id/impact | suppliers.view | Ce que la déconnexion affecterait — les produits liés et les commandes ouvertes auprès des fournisseurs. |
PUT | /:storeId/:id/settings | suppliers.manage | Modifier les propres paramètres du fournisseur. |
PUT | /:storeId/:id/automation | suppliers.manage | Modifier la manière dont les commandes sont envoyées et les limites. |
PUT | /:storeId/:id/enabled | suppliers.manage | Activer ou désactiver la connexion. |
DELETE | /:storeId/:id | suppliers.manage | Déconnecter. Les identifiants sont supprimés et les produits importés restent ceux de la boutique. |
Produits fournisseurs, importations et liens
Section intitulée « Produits fournisseurs, importations et liens »| Méthode | Route | Autorisation | Fonction |
|---|---|---|---|
GET | /:storeId/:id/products | suppliers.import | Parcourez ou recherchez dans le catalogue du fournisseur. |
POST | /:storeId/:id/products/resolve-url | suppliers.import | Transformez un lien de produit collé en ID de produit du fournisseur. |
GET | /:storeId/:id/products/:supplierProductId | suppliers.import | Un produit de fournisseur avec ses variantes, ses coûts et son stock. |
POST | /:storeId/:id/import/preview | suppliers.import | Définissez le prix des produits choisis avec la règle de prix et signalez les doublons. Rien n’est facturé. |
POST | /:storeId/:id/import | suppliers.import | Importez jusqu’à 50 produits. Un import important renvoie un ID de tâche à interroger. |
GET | /:storeId/imports/:jobId | suppliers.import | La progression d’une importation en arrière-plan. |
GET | /:storeId/links | suppliers.view | Les liens de produits de la boutique. |
POST | /:storeId/links | suppliers.import | Associer un produit déjà présent dans la boutique à un produit fournisseur. |
PUT | /:storeId/links/:linkId | suppliers.import | Modifier les variantes, la règle de prix ou les options de synchronisation d’un lien. |
DELETE | /:storeId/links/:linkId | suppliers.import | Dissocier. Le produit reste propre à la boutique. |
POST | /:storeId/links/:linkId/sync | suppliers.import | Synchroniser un lien maintenant. |
Commandes fournisseurs
Section intitulée « Commandes fournisseurs »| Méthode | Route | Autorisation | Fonction |
|---|---|---|---|
GET | /:storeId/orders | suppliers.view | Commandes fournisseurs, de la plus récente à la plus ancienne, filtrées et paginées par curseur. Les champs de requête sont listés sous le tableau. |
GET | /:storeId/orders/:supplierOrderId | suppliers.view | Une commande fournisseur avec son historique. |
POST | /:storeId/orders/:orderId/groups/:groupKey/submit | suppliers.orders.manage | Envoyer une partie d’une commande à son fournisseur maintenant. |
POST | /:storeId/orders/:supplierOrderId/retry | suppliers.orders.manage | Réessayer une commande fournisseur en file d’attente, en pause ou échouée. |
POST | /:storeId/orders/:supplierOrderId/pay | suppliers.orders.manage | Payer une commande fournisseur créée mais non payée. |
POST | /:storeId/orders/:supplierOrderId/cancel | suppliers.orders.manage | Annuler la commande auprès du fournisseur, si celui-ci le permet encore. |
POST | /:storeId/orders/:orderId/groups/:groupKey/fulfil-manually | suppliers.orders.manage | Prendre une partie en charge pour que la boutique l’expédie elle-même. |
La liste accepte ces champs de requête — status, needsReview, integrationId, orderId, contractModel, cursor, pageSize
La liste est paginée par curseur, comme les autres listes de la boutique, et ne prend pas de numéro de page. Une page contient 25 lignes, sauf demande d’une autre taille, et jamais plus de 100. Chaque réponse est une page , les lignes, puis un bloc de pagination avec les curseurs suivant et précédent, l’indication de lignes supplémentaires, le total et la taille de la page —
{ "items": [{ "_id": "SUPPLIER_ORDER_ID", "status": "needsReview" }], "pagination": { "nextCursor": "NEXT_CURSOR", "previousCursor": null, "hasMore": true, "totalCount": 42, "pageSize": 25 }}Pour lire la page suivante, répétez l’appel avec les mêmes filtres et le curseur suivant de la page précédente comme curseur. Arrêtez-vous lorsqu’il n’y a plus de lignes. Lisez chaque page avant d’agir sur les lignes , une nouvelle tentative ou un paiement modifie la liste parcourue par le curseur.
Deux actions acceptent un corps facultatif —
submit—{ "payNow": true }— payer également la commande dès sa création, le fournisseur pouvant être payé à partir d’un solde. Payer maintenant relève de la décision du marchand, la vérification du paiement par l’acheteur est donc ignorée — une commande impayée ou avec paiement à la livraison est également payée, et ce choix est enregistré dans l’historique de la commande fournisseur. Les vérifications de destination, de stock, de limite de coût et de solde s’appliquent toujours.retry—{ "acceptCost": true }— accepter le nouveau coût du fournisseur après un changement de prix. Il est enregistré comme la décision de l’appelant.
Ajouts aux commandes de la boutique
Section intitulée « Ajouts aux commandes de la boutique »GET /api/store-orders/:storeId/:id— Les détails de la commande ajoutent les parties de la commande et, pour un appelant qui dispose aussi de l’autorisation d’affichage des fournisseurs, ses commandes fournisseurs avec leurs coûts.GET /api/store-orders/:storeId?needsAttention=true— Chaque commande de la liste comporte un résumé de ses parties, et la liste accepte un filtre pour les commandes dont une partie nécessite une attention.
Connexion fournisseur
Section intitulée « Connexion fournisseur »supplierKey— Quel fournisseur, tel que nommé dans le catalogue.mode— test ou production.enabled— Si la connexion est activée.hasCredentials— Si les identifiants sont enregistrés. Les identifiants eux-mêmes ne sont jamais renvoyés.automation— Comment les commandes sont envoyées et les limites qui les arrêtent.health— Le résultat de la dernière vérification.isCircuitOpen,circuitOpenUntil— La connexion est suspendue après des erreurs répétées, jusqu’à ce moment-là.lastWebhookAt— Date de la dernière notification envoyée par le fournisseur.webhookUrl— L’adresse à laquelle le fournisseur envoie ses notifications, sur la liste des connexions. Vide lorsqu’aucune adresse publique n’est configurée.
Lien produit
Section intitulée « Lien produit »productId,supplierProductId— Le produit de la boutique et le produit du fournisseur auquel il est lié.variants[]— Chaque variante de la boutique associée à une variante du fournisseur, avec son coût et son stock.priceRule— Comment le prix de la boutique est calculé à partir du coût.sync— Quels champs la synchronisation horaire peut modifier.lastSyncAt,lastSyncError— La dernière synchronisation et, en cas d’échec, la raison.
Commande fournisseur
Section intitulée « Commande fournisseur »status— L’étape où en est la commande fournisseur. Le tableau ci-dessous liste chaque valeur.reviewReason,reviewMessage— La raison de l’arrêt, choisie parmi une liste prédéfinie, et les propos du fournisseur sans aucune information sensible.retryable— Si réessayer sans rien changer peut réussir.supplierOrderNumber— Notre numéro, envoyé au fournisseur comme numéro de commande. Il ne change jamais entre les relances d’une même tentative.supplierOrderId,supplierStatus— L’identifiant et le statut propres au fournisseur, tels qu’il les indique.costs,payment— Le montant facturé par le fournisseur et si la boutique l’a réglé.shipping— Le transporteur et le numéro de suivi une fois que le fournisseur a expédié la commande.attempt,events[]— Le numéro de cette tentative et son historique.destination,destinationRedacted— L’adresse de livraison, uniquement pour un appelant autorisé à voir les données client. Sinon, elle est supprimée et l’indicateur le signale.
dropshipping.developer.objects.paymentValuesList
Sur une commande de boutique
Section intitulée « Sur une commande de boutique »fulfilmentGroups[]— Les parties de la commande — une pour les articles de la boutique et une par connexion fournisseur — chacune avec son statut, ses articles et son expédition.fulfilmentSummary— Le nombre de parties et combien ont été expédiées ou livrées.supplierOrders[]— Les commandes fournisseurs sous-jacentes aux parties, pour un appelant autorisé à voir les fournisseurs.
Statuts et raisons
Section intitulée « Statuts et raisons »Statuts des parties de commande
Section intitulée « Statuts des parties de commande »Une commande avance au rythme de sa partie la plus lente. Elle n’est expédiée que lorsque toutes les parties ont été expédiées, et livrée lorsque toutes ont été livrées.
| Valeur | Signification | Ce qu’un programme peut faire |
|---|---|---|
pending | Pas encore commencé. | Rien — attendez. |
processing | En cours de préparation par la boutique ou le fournisseur. | Rien — attendez. |
shipped | Remis à un transporteur. | Lire le suivi de l’expédition de la partie. |
delivered | Livré. Définitif. | Rien — attendez. |
cancelled | Annulé. Définitif. | Rien — attendez. |
Statuts des commandes fournisseur
Section intitulée « Statuts des commandes fournisseur »| Valeur | Signification | Ce qu’un programme peut faire |
|---|---|---|
queued | En attente d’envoi. | Rien — attendez. |
needsReview | Arrêtée pour une raison précise. Nécessite une intervention humaine ou une modification des données. | À faire vérifier par un opérateur. Ne réessayez qu’après la résolution du problème. |
submitted | Créée chez le fournisseur, pas encore acceptée ni payée. | Effectuez le paiement si la boutique règle manuellement. |
confirmed | Acceptée et payée chez le fournisseur. | Rien — attendez. |
processing | En cours de préparation par le fournisseur. | Rien — attendez. |
shipped | Expédiée par le fournisseur, avec suivi. | Rien — attendez. |
delivered | Livrée. Statut final. | Rien — attendez. |
cancelled | Annulée. Statut final. | Rien — attendez. |
failed | Une erreur temporaire, telle qu’un délai d’attente dépassé. La tâche réessaye automatiquement. | Réessayez une fois, si les tentatives automatiques se sont arrêtées. |
Motifs de révision
Section intitulée « Motifs de révision »Une commande fournisseur en pause comporte exactement un de ces motifs. La deuxième colonne indique la valeur définie par l’API pour chacun d’eux.
| Valeur | retryable | Signification | Ce qu’un programme peut faire |
|---|---|---|---|
insufficientBalance | false | Le solde de la boutique chez le fournisseur ne peut pas couvrir la commande. | Prévenez quelqu’un. Réessayez après avoir rechargé le solde. |
variantUnavailable | false | Le fournisseur ne propose plus cette variante. | Rien sans intervention humaine. |
destinationUnsupported | false | Le fournisseur n’expédie pas vers cette destination ou la boutique a exclu ce pays. | Rien sans intervention humaine. |
costAboveLimit | false | Le coût dépasse la limite définie par la boutique. | Réessayer uniquement sur décision humaine. |
costChanged | false | Le prix du fournisseur a changé depuis l’importation. | Réessayer, en acceptant le nouveau coût, uniquement sur décision humaine. |
customerPaymentPending | false | L’acheteur n’a pas payé en ligne. | Soumettez-le lorsque la boutique le décidera. |
customerPaymentNotSettled | false | Le paiement est autorisé mais non réglé. | Réessayez une fois le paiement réglé. |
connectionUnhealthy | true | Le fournisseur n’a pas répondu ou la connexion est en pause. | Réessayez plus tard. |
supplierRefused | true | Le fournisseur a rejeté la commande. | Lisez le message. Réessayez une fois la cause corrigée. |
connectionMissing | false | La connexion est inactive, a été supprimée ou le fournisseur a été désactivé par Posty5. | Rien. Une personne doit intervenir. |
supplierAlreadyShipped | false | Une demande d’annulation a été reçue après que le fournisseur a déjà expédié la commande. | Rien — traitez-le comme un retour. |
testMode | false | Une connexion de test a été établie avec un fournisseur sans environnement de test (sandbox). Aucune commande n’a été passée. | Rien tant que la connexion n’est pas active. |
customerCaptureFailed | false | Promesse de vente — le fournisseur a été payé, mais le débit de l’acheteur a échoué. | Prévenez quelqu’un immédiatement. |
L’adresse de notification du fournisseur
Section intitulée « L’adresse de notification du fournisseur »POST /api/store-suppliers/webhook/:supplierKey/:integrationIdLes fournisseurs qui envoient des notifications appellent cette adresse pour signaler le statut de la commande, le suivi et le stock.
Posty5 trouve la connexion à partir de l’adresse et vérifie le message avec les propres identifiants de cette connexion. Chaque refus reçoit la même réponse 400, et 503 lorsque Posty5 ne peut pas trancher, ce qui amène le fournisseur à renvoyer. Une notification incite simplement Posty5 à relire la commande auprès du fournisseur. Elle ne déplace jamais d’argent, de stock ou de statut d’elle-même.
Idempotence et nouvelles tentatives
Section intitulée « Idempotence et nouvelles tentatives »Une commande fournisseur est protégée contre les doublons de trois manières.
- Un travail par partie de commande, peu importe ce qui le déclenche —
- Une clé unique par tentative, envoyée au fournisseur comme numéro de commande. Avant la création, Posty5 demande au fournisseur si ce numéro existe déjà, afin qu’une création ayant expiré après avoir réussi soit retrouvée et non répétée.
- Avant de payer, Posty5 lit le statut propre du fournisseur. Une commande déjà payée là-bas est enregistrée, et non payée à nouveau.
Ce que cela signifie pour votre programme
Section intitulée « Ce que cela signifie pour votre programme »- Appeler la soumission deux fois donne une seule commande fournisseur.
- dropshipping.developer.idem.rules.retryWhen
- Une commande en pause ne se résout pas d’elle-même. Elle nécessite une intervention humaine ou une modification des données.
- Pour suivre une commande, lisez à nouveau la commande fournisseur. N’appelez pas la soumission en boucle.
Quand les commandes sont envoyées
Section intitulée « Quand les commandes sont envoyées »Avec un niveau automatique, une partie fournisseur est envoyée une fois, lorsque la commande est confirmée par un membre de l’équipe ou par un paiement en ligne.
Le paiement automatique au fournisseur nécessite que le paiement de l’acheteur soit effectué, tel que confirmé par le fournisseur de services de paiement. Une commande sans paiement en ligne est en attente, sauf si la connexion autorise les commandes impayées.
Dans le cadre de la promesse de vente, l’envoi commence une fois que le paiement de l’acheteur est autorisé, et l’acheteur est débité lorsque le fournisseur accepte.
Exemples
Section intitulée « Exemples »Lister les commandes fournisseur en attente de révision —
curl "https://api.posty5.com/api/store-suppliers/STORE_ID/orders?needsReview=true" \ -H "X-API-Key: YOUR_API_KEY"La réponse est une page de commandes fournisseurs. Une ligne arrêtée pour solde insuffisant se présente ainsi —
{ "_id": "SUPPLIER_ORDER_ID", "orderNumber": "1042", "fulfilmentGroupKey": "GROUP_KEY", "supplierKey": "cjdropshipping", "attempt": 1, "status": "needsReview", "reviewReason": "insufficientBalance", "reviewMessage": "Balance is insufficient", "retryable": false, "supplierOrderNumber": "SUPPLIER_ORDER_NUMBER", "payment": { "status": "unpaid" }}Le même appel depuis TypeScript —
const response = await fetch( `https://api.posty5.com/api/store-suppliers/${storeId}/orders?needsReview=true`, { headers: { "X-API-Key": process.env.POSTY5_API_KEY! } },);const { result } = await response.json();// result.items: the supplier orders on this page// result.pagination.nextCursor: send it back as `cursor` while result.pagination.hasMoreEt depuis C# —
using var http = new HttpClient { BaseAddress = new Uri("https://api.posty5.com") };http.DefaultRequestHeaders.Add("X-API-Key", Environment.GetEnvironmentVariable("POSTY5_API_KEY"));var json = await http.GetStringAsync($"/api/store-suppliers/{storeId}/orders?needsReview=true");// { "result": { "items": [...], "pagination": { "nextCursor": "...", "hasMore": true, ... } } }// Send pagination.nextCursor back as &cursor= while pagination.hasMore is true.SDK et n8n
Section intitulée « SDK et n8n »Les packages de boutique JavaScript et .NET disposent chacun d’un client fournisseurs couvrant tous les groupes ci-dessus — catalogue, connexions, produits fournisseurs, importations, liens et commandes fournisseurs. Lorsqu’une commande fournisseur est suspendue pour révision, soumettre, réessayer et payer déclenchent une erreur au lieu de retourner un résultat, lisez donc à nouveau la commande fournisseur pour en comprendre la raison.
- npm —
@posty5/store4.3.0—store.suppliers - NuGet —
Posty5.Store3.2.0—store.Suppliers
Aucune de ces versions n’est encore publiée. En attendant, appelez directement les routes ci-dessus.
Depuis TypeScript, réessayez chaque commande fournisseur suspendue en raison d’un changement de prix du fournisseur, en acceptant le nouveau coût —
import { HttpClient } from "@posty5/core";import { IStoreSupplierOrder, StoreClient } from "@posty5/store";
const store = new StoreClient(new HttpClient({ apiKey: process.env.POSTY5_API_KEY }));
// Read every page first: a retry changes the list the cursor walks.const paused: IStoreSupplierOrder[] = [];let cursor: string | undefined;do { const page = await store.suppliers.listSupplierOrders(storeId, { needsReview: true, cursor, pageSize: 100 }); paused.push(...page.items); cursor = page.pagination.hasMore ? page.pagination.nextCursor ?? undefined : undefined;} while (cursor);
for (const supplierOrder of paused) { if (supplierOrder.reviewReason === "costChanged") { await store.suppliers.retry(storeId, supplierOrder._id, { acceptCost: true }); }}Et depuis C# —
using Posty5.Core.Configuration;using Posty5.Core.Http;using Posty5.Core.Models;using Posty5.Store;using Posty5.Store.Models;
var http = new Posty5HttpClient(new Posty5Options { ApiKey = Environment.GetEnvironmentVariable("POSTY5_API_KEY") });var store = new StoreClient(http);
// Read every page first: a retry changes the list the cursor walks.var paused = new List<StoreSupplierOrder>();string? cursor = null;do{ var page = await store.Suppliers.ListSupplierOrdersAsync(storeId, new SupplierOrderSearchParams { NeedsReview = true }, new PaginationParams { Cursor = cursor, PageSize = 100 }); if (page == null) break; paused.AddRange(page.Items); cursor = page.Pagination.HasMore ? page.Pagination.NextCursor : null;} while (cursor != null);
foreach (var supplierOrder in paused){ if (supplierOrder.ReviewReason == "costChanged") await store.Suppliers.RetryAsync(storeId, supplierOrder.Id!, acceptCost: true);}Le nœud de la boutique Posty5 pour n8n (version 4.4.0 du package n8n) couvre les fournisseurs, les produits des fournisseurs, les liens de produits, les commandes fournisseurs, les parties de commande et les commandes. Il n’est pas encore publié non plus.