Branche n’importe quel entrepôt sur ProfitDesk.
La Prep API fait de ton logiciel un centre de prép dans ProfitDesk. Les annonces t’arrivent en webhooks signés, tu renvoies réceptions et expéditions, et chaque unité reste traçable de l’achat jusqu’à l’expédition FBA.
- Webhooks signés
- REST API
- OpenAPI 3.1
- Rejeu d’événements
POST https://wms.example.com/webhooks/profitdesk
X-Webhook-Event-Type: inbound.announced
X-Webhook-Signature: sha256=9f2c41…
{
"type": "inbound.announced",
"connection_id": "pcn_812",
"data": {
"inbound": {
"id": "inb_2000000123",
"fulfillment": "FBA",
"tracking_numbers": ["1Z999AA10123456784"],
"lines": [{
"id": "inl_99",
"purchase_id": "pur_4711",
"item": { "sku": "AB-123", "asin": "B0ABCDEFGH" },
"quantity_expected": 6
}]
}
}
}POST /v1/prep/inbounds/inb_2000000123/receipts
Authorization: Bearer ppk_3f9a…
{
"event_id": "rcpt-8812",
"status": "received",
"lines": [{ "line_id": "inl_99", "quantity_received": 6 }]
}Deux façons de commencer
Une API, pensée pour deux types de développeurs.
- 1Ajoute ton logicielParamètres → Intégrations → Centres de prép → Ajouter → « Logiciel propre (Webhook) ». Renseigne ton endpoint HTTPS et choisis les événements voulus.
- 2Enregistre deux identifiantsUn secret de signature (whsec_…) et une clé API (ppk_…), affichés une seule fois. Tu peux les renouveler à tout moment.
- 3Associe un entrepôtLes achats de cet entrepôt sont désormais annoncés à ton logiciel.
- Portée de la clé
- Cette seule connexion
- Limite de débit
- 2 req/s, pics de 10
- Tests
- Ping « Envoyer un test » et journal des livraisons
- Combinable
- Avec PrepBusiness ou PrepTool, par entrepôt
Comment ça marche
De l’achat à l’expédition FBA,
en cinq événements.
- 01ProfitDeskLa marchandise est en route
inbound.announcedUn webhook signé avec lignes, SKU, ASIN et suivi. Réponds 2xx, éventuellement avec ton propre external_id. - 02ProfitDeskLes détails suivent
inbound.updatedNouveaux numéros de suivi et FNSKU dès qu’Amazon l’attribue, pour que tu puisses imprimer les étiquettes. - 03ToiTu comptes la marchandise
POST …/receiptsQuantités absolues par ligne, unités endommagées incluses. ProfitDesk met l’achat à jour. - 04ToiTu l’expédies
POST /v1/Les lignes et l’identifiant d’expédition FBA relient ton expédition à celle d’Amazon.prep/ outbounds - 05AmazonAmazon réceptionne
FBA15XYZProfitDesk comptabilise la quantité transférée à partir des données d’Amazon. Ton expédition sert de trace.
Chaque unité, traçable de bout en bout.
Chaque objet porte un id avec un préfixe de type. L’id d’achat ne change jamais, même si la marchandise est réannoncée ou change d’entrepôt.
pur_4711AchatL’achat du vendeur. La clé pour suivre une unité, pour toujours.inb_2000000123InboundUne annonce. Une réannonce en reçoit une nouvelle.inl_99Ligne d’inboundUn achat à l’intérieur. À utiliser dans les réceptions et les expéditions.out_55OutboundCe que tu as expédié, adressé par ton propre external_id.FBA15XYZExpédition FBAL’identifiant d’expédition d’Amazon, lié depuis ton outbound.
Utilise aussi tes propres références : tout chemin qui prend un id accepte également ext:<ton id>.
Prêt pour la production
Les parties pénibles
sont déjà réglées.
HMAC-SHA256 en une douzaine de lignes.
Signe le corps brut avec ton secret whsec_ et le timestamp, compare en temps constant, rejette tout ce qui date de plus de cinq minutes. Pendant une rotation du secret, les deux signatures sont envoyées pendant 24 heures.
import crypto from "node:crypto";
function verify(rawBody, headers, secret) {
const ts = headers["x-webhook-timestamp"];
const signature = headers["x-webhook-signature"];
if (!ts || !signature || !/^\d+$/.test(ts)) return false;
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const expected = "sha256=" + crypto.createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
return signature.split(",").some((sig) => {
const a = Buffer.from(sig.trim()), b = Buffer.from(expected);
return a.length === b.length && crypto.timingSafeEqual(a, b);
});
}import hashlib, hmac, time
def verify(raw_body: bytes, headers, secret: str) -> bool:
ts = headers.get("X-Webhook-Timestamp", "")
signature = headers.get("X-Webhook-Signature", "")
if not ts.isdigit() or not signature:
return False
if abs(time.time() - int(ts)) > 300:
return False
expected = "sha256=" + hmac.new(secret.encode(), ts.encode() + b"." + raw_body, hashlib.sha256).hexdigest()
return any(hmac.compare_digest(sig.strip(), expected) for sig in signature.split(","))function verify(string $rawBody, array $headers, string $secret): bool {
$ts = $headers['X-Webhook-Timestamp'] ?? '';
$signature = $headers['X-Webhook-Signature'] ?? '';
if (!ctype_digit($ts) || $signature === '') return false;
if (abs(time() - (int)$ts) > 300) return false;
$expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $rawBody, $secret);
foreach (explode(',', $signature) as $sig) {
if (hash_equals($expected, trim($sig))) return true;
}
return false;
}func verify(rawBody []byte, h http.Header, secret string) bool {
ts := h.Get("X-Webhook-Timestamp")
sec, err := strconv.ParseInt(ts, 10, 64)
if err != nil || math.Abs(float64(time.Now().Unix()-sec)) > 300 {
return false
}
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(ts + "."))
mac.Write(rawBody)
expected := "sha256=" + hex.EncodeToString(mac.Sum(nil))
for _, sig := range strings.Split(h.Get("X-Webhook-Signature"), ",") {
if hmac.Equal([]byte(strings.TrimSpace(sig)), []byte(expected)) {
return true
}
}
return false
}Endpoints
URL de base https://api.profitpath.app · Bearer ppk_…
| GET | /v1/La connexion de la clé | La connexion de la clé |
| GET | /v1/Lister les inbounds | Lister les inbounds |
| GET | /v1/Un inbound, aussi via ext: | Un inbound, aussi via ext: |
| PUT | /v1/Définir ta référence | Définir ta référence |
| POST | /v1/Déclarer la marchandise reçue | Déclarer la marchandise reçue |
| POST | /v1/Déclarer une expédition | Déclarer une expédition |
| GET | /v1/Une expédition | Une expédition |
| GET | /v1/Articles, un par SKU | Articles, un par SKU |
| GET | /v1/Rejouer les événements webhook | Rejouer les événements webhook |
Événements webhook
Livrés au moins une fois, dans l’ordre par inbound.
connection.created · updated · removedUn vendeur se connecte, modifie ses infos ou part | Prestataires |
inbound.announcedLa marchandise est en route vers toi | Actif |
inbound.updatedSuivi, FNSKU, external id ou lignes modifiés | Actif |
inbound.cancelledAnnulé, déplacé ou réannoncé | Actif |
inbound.restoredUn inbound annulé est de nouveau actif | Actif |
inbound.receivedÉcho de ta propre réception | Sur option |
outbound.recordedÉcho de ta propre expédition | Sur option |
ping« Envoyer un test » depuis ProfitDesk | Logiciel propre |
Doc pour ton propre logiciel
FAQ
Questions de développeurs
Si tu utilises ton propre logiciel d’entrepôt pour ton activité Amazon, utilise la connexion logiciel propre dans les paramètres ProfitDesk. Si tu développes un logiciel utilisé par de nombreux centres de prép ou vendeurs, fais-toi référencer comme prestataire de prép : un endpoint et une clé couvrent tous les vendeurs.
Avec ton propre logiciel, utilise un entrepôt de test et un achat de test dans ton compte, et « Envoyer un test » pour vérifier la connectivité. En tant que prestataire de prép, demande-nous une connexion de test depuis un compte vendeur test, et fais tourner tout le flux avant la connexion de ton premier vrai vendeur. Les événements peuvent toujours être rejoués.
La marchandise est annoncée dès que l’annonce Amazon existe. Amazon attribue le FNSKU un peu plus tard, et il arrive dans inbound.updated.
ProfitDesk réessaie jusqu’à 72 heures. Ensuite, tu peux rattraper ton retard à tout moment avec GET /v1/prep/events.
Non. Les expéditions servent de trace. Les quantités transférées viennent des données d’expédition d’Amazon, reliées via l’identifiant d’expédition FBA que tu envoies.
Oui. Interroge GET /v1/prep/events chaque minute à partir du dernier id d’événement traité, et dédoublonne par id.
Tu développes un logiciel de prép
pour plusieurs vendeurs ?
Fais-toi lister dans le sélecteur de centres de prép de chaque vendeur ProfitDesk. Un endpoint et une clé couvrent tous les vendeurs.
support@profitpath.com