Aller au contenu

API de dropshipping

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


Chaque requête transporte votre clé API dans cet en-tête —

Fenêtre de terminal
X-API-Key: YOUR_API_KEY

Cré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.


  • 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.

MéthodeRouteAutorisationFonction
GET/:storeId/cataloguesuppliers.viewLes fournisseurs que cette boutique peut connecter, avec ce que chacun peut faire.
GET/:storeIdsuppliers.viewConnexions des fournisseurs de la boutique, avec état de santé et automatisation. Les identifiants ne sont jamais renvoyés.
POST/:storeIdsuppliers.manageConnecter un fournisseur avec sa clé API. La clé est vérifiée auprès du fournisseur avant d’être enregistrée.
POST/:storeId/oauth/startsuppliers.manageCommencer à connecter un fournisseur qui utilise la connexion, comme AliExpress. Renvoie l’adresse vers laquelle le marchand sera redirigé.
PUT/:storeId/:idsuppliers.manageRemplacer les identifiants de la connexion.
POST/:storeId/:id/testsuppliers.manageVérifier la connexion maintenant et enregistrer son état de santé.
GET/:storeId/:id/balancesuppliers.viewLe solde du compte chez le fournisseur, lorsque le fournisseur en signale un.
GET/:storeId/:id/impactsuppliers.viewCe que la déconnexion affecterait — les produits liés et les commandes ouvertes auprès des fournisseurs.
PUT/:storeId/:id/settingssuppliers.manageModifier les propres paramètres du fournisseur.
PUT/:storeId/:id/automationsuppliers.manageModifier la manière dont les commandes sont envoyées et les limites.
PUT/:storeId/:id/enabledsuppliers.manageActiver ou désactiver la connexion.
DELETE/:storeId/:idsuppliers.manageDéconnecter. Les identifiants sont supprimés et les produits importés restent ceux de la boutique.
MéthodeRouteAutorisationFonction
GET/:storeId/:id/productssuppliers.importParcourez ou recherchez dans le catalogue du fournisseur.
POST/:storeId/:id/products/resolve-urlsuppliers.importTransformez un lien de produit collé en ID de produit du fournisseur.
GET/:storeId/:id/products/:supplierProductIdsuppliers.importUn produit de fournisseur avec ses variantes, ses coûts et son stock.
POST/:storeId/:id/import/previewsuppliers.importDéfinissez le prix des produits choisis avec la règle de prix et signalez les doublons. Rien n’est facturé.
POST/:storeId/:id/importsuppliers.importImportez jusqu’à 50 produits. Un import important renvoie un ID de tâche à interroger.
GET/:storeId/imports/:jobIdsuppliers.importLa progression d’une importation en arrière-plan.
GET/:storeId/linkssuppliers.viewLes liens de produits de la boutique.
POST/:storeId/linkssuppliers.importAssocier un produit déjà présent dans la boutique à un produit fournisseur.
PUT/:storeId/links/:linkIdsuppliers.importModifier les variantes, la règle de prix ou les options de synchronisation d’un lien.
DELETE/:storeId/links/:linkIdsuppliers.importDissocier. Le produit reste propre à la boutique.
POST/:storeId/links/:linkId/syncsuppliers.importSynchroniser un lien maintenant.
MéthodeRouteAutorisationFonction
GET/:storeId/orderssuppliers.viewCommandes 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/:supplierOrderIdsuppliers.viewUne commande fournisseur avec son historique.
POST/:storeId/orders/:orderId/groups/:groupKey/submitsuppliers.orders.manageEnvoyer une partie d’une commande à son fournisseur maintenant.
POST/:storeId/orders/:supplierOrderId/retrysuppliers.orders.manageRéessayer une commande fournisseur en file d’attente, en pause ou échouée.
POST/:storeId/orders/:supplierOrderId/paysuppliers.orders.managePayer une commande fournisseur créée mais non payée.
POST/:storeId/orders/:supplierOrderId/cancelsuppliers.orders.manageAnnuler la commande auprès du fournisseur, si celui-ci le permet encore.
POST/:storeId/orders/:orderId/groups/:groupKey/fulfil-manuallysuppliers.orders.managePrendre 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.
  • 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.

  • 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.
  • 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.
  • 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

  • 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.

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.

ValeurSignificationCe qu’un programme peut faire
pendingPas encore commencé.Rien — attendez.
processingEn cours de préparation par la boutique ou le fournisseur.Rien — attendez.
shippedRemis à un transporteur.Lire le suivi de l’expédition de la partie.
deliveredLivré. Définitif.Rien — attendez.
cancelledAnnulé. Définitif.Rien — attendez.
ValeurSignificationCe qu’un programme peut faire
queuedEn attente d’envoi.Rien — attendez.
needsReviewArrê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.
submittedCréée chez le fournisseur, pas encore acceptée ni payée.Effectuez le paiement si la boutique règle manuellement.
confirmedAcceptée et payée chez le fournisseur.Rien — attendez.
processingEn cours de préparation par le fournisseur.Rien — attendez.
shippedExpédiée par le fournisseur, avec suivi.Rien — attendez.
deliveredLivrée. Statut final.Rien — attendez.
cancelledAnnulée. Statut final.Rien — attendez.
failedUne 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.

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.

ValeurretryableSignificationCe qu’un programme peut faire
insufficientBalancefalseLe 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.
variantUnavailablefalseLe fournisseur ne propose plus cette variante.Rien sans intervention humaine.
destinationUnsupportedfalseLe fournisseur n’expédie pas vers cette destination ou la boutique a exclu ce pays.Rien sans intervention humaine.
costAboveLimitfalseLe coût dépasse la limite définie par la boutique.Réessayer uniquement sur décision humaine.
costChangedfalseLe prix du fournisseur a changé depuis l’importation.Réessayer, en acceptant le nouveau coût, uniquement sur décision humaine.
customerPaymentPendingfalseL’acheteur n’a pas payé en ligne.Soumettez-le lorsque la boutique le décidera.
customerPaymentNotSettledfalseLe paiement est autorisé mais non réglé.Réessayez une fois le paiement réglé.
connectionUnhealthytrueLe fournisseur n’a pas répondu ou la connexion est en pause.Réessayez plus tard.
supplierRefusedtrueLe fournisseur a rejeté la commande.Lisez le message. Réessayez une fois la cause corrigée.
connectionMissingfalseLa connexion est inactive, a été supprimée ou le fournisseur a été désactivé par Posty5.Rien. Une personne doit intervenir.
supplierAlreadyShippedfalseUne 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.
testModefalseUne 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.
customerCaptureFailedfalsePromesse de vente — le fournisseur a été payé, mais le débit de l’acheteur a échoué.Prévenez quelqu’un immédiatement.

POST /api/store-suppliers/webhook/:supplierKey/:integrationId

Les 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.


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.
  • 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.

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.


Lister les commandes fournisseur en attente de révision —

Fenêtre de terminal
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.hasMore

Et 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.

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/store 4.3.0 — store.suppliers
  • NuGet — Posty5.Store 3.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.