v1 · API Partenaire

API Partenaire pour les transitaires

Soumettez des demandes d'approvisionnement pour le compte de vos clients, recevez des cotations chiffrées, téléchargez des preuves de paiement et recevez les mises à jour de statut via des webhooks signés, le tout en HTTPS avec une seule clé API.

Vue d'ensemble

L'API Partenaire permet à un transitaire ou à un partenaire d'approvisionnement tiers de créer des commandes dans notre plateforme par programmation. Chaque commande suit le même pipeline d'exécution que celles créées depuis notre interface, et le partenaire reçoit des notifications webhook à chaque changement d'état important.

Soumettre des commandes
Créez des demandes avec une ou plusieurs destinations.
Recevoir des cotations
Obtenez des prix par destination via webhook et e-mail.
Téléverser des fichiers
Envoyez images, PDF et vidéos vers notre bucket S3, obtenez une URL permanente.
Découvrir les services
Listez le catalogue des transitaires que nous supportons par pays.
Modifier et annuler
Modifiez les destinations tant que la commande est en Processing ou Unpaid.
Webhooks signés
Flux d'événements signé HMAC-SHA256 pour cotations, statuts et médias.
URL de base : https://kuaisourcing.com/api-backTous les endpoints ci-dessous sont relatifs à cette base.

Authentification

Chaque requête doit inclure votre clé API dans l'en-tête x-api-key. La clé identifie le compte partenaire qui appelle, gardez-la secrète.

http
POST /api/partner/sourcing HTTP/1.1
Host: kuaisourcing.com
Content-Type: application/json
x-api-key: ks_live_yourkeyhere1234567890abcdef
Gardez votre clé secrète

Ne placez jamais la clé dans du code côté client et ne la commitez pas sur git. Traitez-la comme un mot de passe. Si elle est exposée, demandez à votre gestionnaire de compte de la régénérer, l'ancienne clé est révoquée immédiatement.

Cycle de vie d'une commande

Une commande passe par les états suivants. Le webhook order.status_changed se déclenche à chaque transition.

ProcessingUnpaidPayment pendingPaidIn ProductionPackedShippedIn TransitDelivered to Destination

Statuts terminaux hors-parcours : Cancelled, Refunded, Order Rejected, OutOfStock.

Soumettre une demande d'approvisionnement

POST/api/partner/sourcing

Une requête peut contenir plusieurs destinations. Chaque destination doit déclarer son transporteur, depuis notre catalogue ou auto-géré.

json
{
  "productName": "Bluetooth Earbuds Pro",
  "productImageUrl": "https://yourcdn.com/img.jpg",
  "productURL": "https://supplier-page.example/product/123",
  "category": "Electronics",
  "targetMarket": "Africa",
  "additionalNotes": "Need OEM packaging",

  "airFreight": true,
  "seaFreight": false,
  "byTrain": false,
  "expressDelivery": false,
  "normalDelivery": true,
  "domesticDelivery": "slow",
  "shippingResponsibility": "kuai",

  "destinations": [
    {
      "country": "Gabon",
      "city": "Libreville",
      "address": "1 Example Street",
      "quantity": 50,
      "variants": "[{\"color\":\"Black\",\"quantity\":30},{\"color\":\"White\",\"quantity\":20}]",
      "service": "DHL",
      "recipientName": "Jane Doe",
      "contactNumber": "+241 00 00 00 00"
    },
    {
      "country": "Tunisia",
      "city": "Tunis",
      "quantity": 30,
      "service": "Other ...",
      "customService": "Local forwarder name",
      "recipientName": "John Doe",
      "contactNumber": "+216 00 000 000",
      "isCompanyService": false
    }
  ]
}

Champs de premier niveau

ChampRequisNotes
productNameouiLibellé court du produit
targetMarketouiex. "Africa"
destinationsouiAu moins une entrée. Chaque entrée doit avoir country + quantity.
airFreight / seaFreight / byTrainun doit être vraiSi airFreight est true, définissez aussi expressDelivery ou normalDelivery.
domesticDeliveryoptionnel"fast" ou "slow" (en Chine)
shippingResponsibilityoptionnel"kuai" / "service" / "self"
productImageUrloptionnelDoit être accessible. Téléversez d'abord via l'endpoint uploads pour plus de sûreté.

Réponse ·
201 Created

json
{
  "success": true,
  "data": {
    "orderId": "9f5e2c3a-...",
    "customOrderId": "KS0000",
    "message": "Sourcing request submitted successfully"
  }
}

Utilisez orderId (UUID) pour les appels suivants. customOrderId (KS0001, KS0002, …) est le même identifiant séquentiel que celui affiché dans notre tableau de bord interne.

Lister vos commandes

GET/api/partner/sourcing?status=Unpaid&details=true&page=0&size=50
ParamètreDéfautNotes
status(any)Filtrer par statut exact (voir section cycle de vie)
detailstruefalse pour une charge utile plus légère (sans cotations / images / destinations)
page0Indexé à partir de zéro
size100Maximum 100

Renvoie une Page Spring de commandes (voir Récupérer une commande pour la structure).

Récupérer une commande

GET/api/partner/sourcing/{orderId}
GET/api/partner/sourcing/by-order-id/{customOrderId}

Les deux formes renvoient la même charge utile.

json
{
  "success": true,
  "data": {
    "id": "9f5e2c3a-...",
    "customOrderId": "KS0000",
    "productName": "Bluetooth Earbuds Pro",
    "status": "Unpaid",
    "formCreationDate": "2026-05-10T08:14:32",
    "lastUpdated": "2026-05-13T11:02:08",
    "realImages": [
      { "id": "...", "image": "https://files.example.com/uploads/real-1.jpg",  "addedAt": "2026-05-13T10:55:00" },
      { "id": "...", "image": "https://files.example.com/uploads/demo.mp4",   "addedAt": "2026-05-13T11:00:00" }
    ],
    "destinations": [
      {
        "id": "d4...",
        "country": "Gabon",
        "city": "Libreville",
        "quantity": 50,
        "service": { "name": "DHL", "recipientName": "Jane Doe" },
        "quotation": {
          "totalCost": 1840.00,
          "unitPrice": 35.00,
          "internationalShippingCost": 90.00,
          "deliveryCostInChina": 70.00,
          "extraFees": 0.00
        }
      }
    ]
  }
}

Modifier une commande

PUT/api/partner/sourcing/{orderId}

Même structure que la soumission. Repassez l'id de chaque destination pour la mettre à jour sur place (préserve la cotation liée). Les destinations absentes de la requête sont supprimées ; celles sans id sont créées.

Modifiable uniquement quand le statut est Processing ou Unpaid. Tout autre statut renvoie 409 Conflict.

Téléverser un fichier

POST/api/partner/uploads

Formulaire multipart. Renvoie une URL S3 permanente que vous pouvez réutiliser comme productImageUrl, url de proof-of-payment, etc.

bash
curl -X POST https://kuaisourcing.com/api-back/api/partner/uploads \
  -H "x-api-key: $KEY" \
  -F "file=@receipt.pdf" \
  -F "purpose=proof-of-payment"

# Response
{
  "success": true,
  "data": {
    "url": "https://files.example.com/uploads/receipt.pdf",
    "size": 27695,
    "contentType": "application/pdf"
  }
}

Acceptés : jpg, jpeg, png, webp, pdf, mp4, mov, webm. 25 Mo maximum.

Soumettre une preuve de paiement

POST/api/partner/sourcing/{orderId}/proof-of-payment

Attachez un reçu à une commande existante. Téléversez d'abord le fichier via l'endpoint uploads et passez l'URL renvoyée ici.

json
{
  "country": "Gabon",
  "url": "https://files.example.com/uploads/receipt.pdf",
  "paymentNote": "Bank transfer EUR to USD, reference KS0000"
}

En cas de succès, le statut passe automatiquement de Unpaid à Payment pending et un webhook order.status_changed est émis.

Lister les services disponibles

Dédupliqué par nom (insensible à la casse). Un service peut opérer dans plusieurs pays, chaque ligne montre la liste de couverture.

GET/api/partner/services
json
{
  "success": true,
  "data": [
    { "id": "00000000-0000-4000-8000-000000000001", "name": "Example Freight Co", "countries": ["Morocco"] },
    { "id": "00000000-0000-4000-8000-000000000002", "name": "Sample Logistics",   "countries": ["Senegal", "Madagascar"] },
    { "id": "00000000-0000-4000-8000-000000000003", "name": "Demo Shipping Line", "countries": ["Spain"] }
  ]
}

Règles de sélection de service

Champ envoyéComportement
serviceIdPréféré, non ambigu, lie à cette ligne du catalogue
serviceCorrespondance par nom, insensible à la casse. "DHL" = "dhl" = "Dhl".
service: "Other ..."Voir la livraison auto-gérée, champs supplémentaires requis.
Toute autre valeur400 avec "Service 'X' is not in our catalog…"

Livraison auto-gérée

Quand vous gérez vous-même la livraison, votre coursier, un transitaire local, ou un retrait personnel, définissez service: "Other ..." sur la destination et fournissez les mêmes champs qu'un utilisateur normal remplit dans notre interface.

ChampRequisRôle
customService
oui
Nom libre du transitaire/coursier (ex. "Mon transitaire local de Tunis")
recipientName
oui
Personne recevant à destination
contactNumber
oui
Téléphone du destinataire, utilisé par le coursier local
isCompanyServiceoptionnelDéfaut false. Mettez true pour les transitaires entreprise déclarés.
address, cityoptionnelHérité de la destination, également utilisé comme adresse de livraison.

Ces lignes sont marquées userSubmitted=true côté serveur, elles n'apparaissent donc jamais dans le catalogue partagé des services.

Si un champ requis manque, l'API renvoie 400 avec un pointeur vers cette section.

Webhooks

Configurez une URL de webhook lors du provisioning de votre clé API. Nous livrons les événements de manière asynchrone, signés en HMAC-SHA256, avec réessais en cas d'échec.

ÉvénementDéclenché quand…
quotation.createdUn admin émet une cotation chiffrée sur une de vos destinations
quotation.updatedUne cotation existante est modifiée
order.status_changedLe statut change (ex. Unpaid → Paid → In Production → Shipped)
realimages.addedDes photos / vidéos du produit réel sont téléversées

Si un notificationEmail est aussi configuré sur votre clé, les mêmes événements déclenchent un e-mail digest parallèle. Les deux canaux sont optionnels.

Livraison + réessais

Meilleur effort. Nous réessayons sur les réponses non-2xx avec backoff exponentiel (1 s, 2 s, 4 s, 8 s, 16 s). Répondez 2xx dans les 10 secondes ou la tentative est considérée comme échouée.

Format des erreurs

Toutes les erreurs partagent la même enveloppe. Le statut HTTP est porteur de sens, votre client doit l'aiguiller avant de lire le corps.

json
HTTP 400 Bad Request
{
  "success": false,
  "data": null,
  "error": "destinations: At least one destination is required",
  "timestamp": "2026-05-18T11:42:03.581"
}
CodeSignification
400Validation échouée, voir le champ error pour le détail. Ne réessayez pas sans corriger.
401x-api-key manquante ou invalide
403Clé révoquée ou quota dépassé
404Commande ou ressource non trouvée (ou non détenue par votre clé)
409Commande dans un statut non modifiable, modification impossible
429Limite de débit, temporisez et réessayez
500Erreur serveur, réessai sûr avec backoff exponentiel

Aide-mémoire des endpoints

Méthode · CheminCe que ça fait
POST /api/partner/sourcingCréer une demande d'approvisionnement
GET /api/partner/sourcingLister vos commandes (paginées, filtrables)
GET /api/partner/sourcing/{orderId}Récupérer une commande (détail complet)
GET /api/partner/sourcing/by-order-id/{customOrderId}Idem, par code KS
PUT /api/partner/sourcing/{orderId}Modifier (seulement Processing / Unpaid)
POST /api/partner/uploadsTéléverser un fichier → URL S3 permanente
POST /api/partner/sourcing/{orderId}/proof-of-paymentAttacher un reçu ; le statut passe Unpaid → Payment pending
GET /api/partner/servicesLister le catalogue des services de livraison
Envie d'intégrer ?
Écrivez à avec le nom de votre entreprise + l'URL de webhook où vous recevrez. Nous provisionnons les clés en moins de 24 h.
État & disponibilité
Nous visons 99,9 % sur l'API. Si vous observez des 5xx persistants ou un silence webhook, écrivez à contact@kuaisourcing.com.
Kuai Sourcing: China Sourcing & Freight to 85+ Countries