Shipper Open API

Integrez votre systeme avec Shipper pour creer et suivre les commandes automatiquement.

v1https://server.shipper.network/api/v1PostmanTelecharger la collection Postman

Premiers pas

L'Open API Shipper est une API REST qui vous permet de :

  • Creer des commandes automatiquement depuis votre systeme
  • Recuperer les details des commandes et le suivi des expeditions
  • Listez et recherchez vos produits et commandes
  • Annulez des commandes par programmation
  • Recevez des mises a jour de statut en temps reel via webhooks

Pour commencer, generez une cle API depuis votre tableau de bord Shipperdans Integrations > API.


Authentification

Toutes les requetes API necessitent un token Bearer dans l'en-tete Authorization.

Authorization: Bearer YOUR_API_KEY
Accept: application/json
Content-Type: application/json
Limites de debit

Les requetes sont limitees par cle API. Depasser la limite retourne HTTP 429 (Too Many Requests).

Type de point d'accesLimitePoints d'acces
Lecture120req/minGET /products, /orders, /orders/:id, /webhooks
Reference60req/minGET /countries, /countries/:code/divisions
Ecriture30req/minPOST /orders, /webhooks
Destructif20req/minPOST /orders/:id/cancel, DELETE /webhooks/:id

Les en-tetes de limite (X-RateLimit-Limit, X-RateLimit-Remaining) sont inclus dans chaque reponse.


Geographie

GETGET /countries

Retourne tous les pays supportes avec leur structure geographique. Utilisez ceci pour comprendre quels niveaux de division (gouvernorat, delegation, etc.) sont requis pour chaque pays.

Exemple de requete
curl https://server.shipper.network/api/v1/countries \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
Reponse

200

[
  {
    "code": "TN",
    "name": "Tunisia",
    "geo_structure": {
      "fields": [
        { "id": "division_1_id", "label": "Governorate", "level": 1, "required": true, "depends_on": null },
        { "id": "division_2_id", "label": "Delegation", "level": 2, "required": true, "depends_on": "division_1_id" }
      ]
    }
  }
]

Le tableau geo_structure.fields vous indique combien de niveaux de division existent, leurs libelles et dependances. Utilisez depends_on pour construire des listes en cascade.

GETGET /countries/{code}/divisions

Retourne les noms des divisions pour un pays. Utilisez-le pour obtenir les valeurs valides pour address.division_1 et address.division_2 lors de la creation de commandes.

Parametres de requete
ParametreTypeRequisDescription
levelinteger-Niveau de division (defaut : 1 = niveau superieur)
parent_idinteger-Filtrer par ID de division parente pour obtenir les enfants
Exemple : Divisions de premier niveau
curl https://server.shipper.network/api/v1/countries/TN/divisions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
{
  "country": "TN",
  "geo_structure": { ... },
  "divisions": [
    { "id": 1, "name": "Tunis", "level": 1, "parent_id": null },
    { "id": 2, "name": "Sfax", "level": 1, "parent_id": null },
    { "id": 3, "name": "Sousse", "level": 1, "parent_id": null }
  ]
}
Exemple : Sous-divisions sous un parent
curl "https://server.shipper.network/api/v1/countries/TN/divisions?level=2&parent_id=1" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
{
  "country": "TN",
  "geo_structure": { ... },
  "divisions": [
    { "id": 10, "name": "Bab El Bhar", "level": 2, "parent_id": 1 },
    { "id": 11, "name": "Bab Souika", "level": 2, "parent_id": 1 },
    { "id": 12, "name": "Carthage", "level": 2, "parent_id": 1 }
  ]
}

Produits

GETGET /products

Retourne votre catalogue produits avec les UUIDs. Vous avez besoin des UUIDs pour creer des commandes via l'API.

Parametres de requete
ParametreTypeRequisDescription
pageinteger-Numero de page (defaut : 1)
per_pageinteger-Elements par page (defaut : 20, max : 100)
searchstring-Rechercher par nom de produit ou SKU
Exemple de requete
curl "https://server.shipper.network/api/v1/products?per_page=10&search=shirt" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
Reponse

200

{
  "data": [
    {
      "uuid": "2e97b37a-3118-4905-842c-19706bcf1455",
      "name": "Blue T-Shirt",
      "sku": "SKU-001",
      "price": 190,
      "status": "active",
      "available_qte": 42,
      "variants": [
        {
          "uuid": "a1b2c3d4-5678-9012-abcd-ef0123456789",
          "name": "Size L",
          "sku": "SKU-001-L",
          "price": 190,
          "available_qte": 15
        }
      ]
    }
  ],
  "pagination": { "total": 50, "current_page": 1, "per_page": 10, "last_page": 5 }
}

GETGET /products/{uuid}

Retourne un produit par UUID, incluant ses variantes et les quantites disponibles en stock.

Exemple de requete
curl https://server.shipper.network/api/v1/products/2e97b37a-3118-4905-842c-19706bcf1455 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
Reponse

200

{
  "uuid": "2e97b37a-3118-4905-842c-19706bcf1455",
  "name": "Blue T-Shirt",
  "sku": "SKU-001",
  "price": 190,
  "status": "active",
  "available_qte": 42,
  "variants": [
    { "uuid": "a1b2c3d4-...", "name": "Size L", "sku": "SKU-001-L", "price": 190, "available_qte": 15 },
    { "uuid": "e5f6a7b8-...", "name": "Size M", "sku": "SKU-001-M", "price": 190, "available_qte": 27 }
  ]
}

Commandes

GETGET /orders

Retourne une liste paginee de vos commandes. Utilisez les filtres pour affiner par statut, plage de dates ou termes de recherche.

Parametres de requete
ParametreTypeRequisDescription
pageinteger-Numero de page (defaut : 1)
per_pageinteger-Elements par page (defaut : 20, max : 100)
statusstring-Filtrer par statut d'expedition (ex: delivered, awaitingpackaging, canceled)
start_datestring-Filtrer les commandes creees a partir de cette date (AAAA-MM-JJ)
end_datestring-Filtrer les commandes creees jusqu'a cette date (AAAA-MM-JJ)
searchstring-Rechercher par ID de commande, nom du client ou numero de telephone
Exemple de requete
curl "https://server.shipper.network/api/v1/orders?status=delivered&start_date=2025-01-01&per_page=10" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
Reponse

200

{
  "data": [
    {
      "id": 555,
      "status": "Paid",
      "store_name": "My Store",
      "is_cod": true,
      "is_paid": true,
      "created_at": "2025-01-10T10:00:00.000000Z",
      "address": { "first_name": "Omar", "last_name": "Ben Ali", "phone1": "+21628177188" },
      "items_count": 2,
      "shipments_count": 1,
      "external_order_id": "ORD-123",
      "external_order_url": "https://mystore.com/orders/123"
    }
  ],
  "pagination": { "total": 150, "current_page": 1, "per_page": 10, "last_page": 15 }
}

POSTPOST /orders

Cree une nouvelle commande dans Shipper. Retourne l'ID de commande que vous pouvez utiliser pour suivre la commande.

Corps de la requete
ParametreTypeRequisDescription
addressobject*Objet adresse du destinataire (voir les champs ci-dessous)
address.namestring*Nom complet - separe automatiquement en prenom et nom
address.phone1string*Numero de telephone principal
address.phone2string-Numero de telephone secondaire
address.address1string*Adresse ligne 1
address.address2string-Adresse ligne 2
address.division_1string-Etat / Gouvernorat - utilisez le nom exact de GET /countries/{code}/divisions
address.division_2string-Ville / Delegation - utilisez le nom exact de GET /countries/{code}/divisions?level=2&parent_id=...
address.countrystring*Code pays a deux lettres (ex: TN, DZ, MA)
itemsarray*Tableau des articles de la commande
items[].idstring*UUID du produit ou de la variante de GET /products
items[].quantityinteger-Quantite (defaut : 1)
items[].total_pricenumber-Prix total pour cette ligne. Par defaut : prix du produit x quantite
shipping_totalnumber-Frais de livraison factures au client (defaut : 0)
is_codboolean-)
auto_fulfillboolean-Envoyer directement en preparation sans creer de brouillon (defaut : false)
with_confirmationboolean-Exiger un appel de confirmation avant l'expedition (defaut : false)
store_namestring-Nom du magasin source - apparait dans le suivi pour votre reference
external_order_idstring-ID de reference de votre systeme - affiche dans le tableau de bord Shipper
external_order_urlstring-URL de la commande dans votre systeme - cliquable depuis le tableau de bord Shipper
Exemple de requete
curl -X POST https://server.shipper.network/api/v1/orders \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "address": {
      "name": "Omar Ben Ali",
      "division_1": "Tunis",
      "division_2": null,
      "phone1": "28177188",
      "address1": "Rue de la Liberte",
      "country": "TN"
    },
    "items": [
      { "quantity": 1, "id": "YOUR_PRODUCT_UUID", "total_price": 190 }
    ],
    "shipping_total": 9,
    "is_cod": true,
    "auto_fulfill": true,
    "with_confirmation": true,
    "store_name": "My Store",
    "external_order_id": "ORD-12345",
    "external_order_url": "https://mystore.com/orders/12345"
  }'
Reponse

201Cree

{
  "id": 555
}

GETGET /orders/{id}

Retourne les details complets de la commande incluant le statut, les numeros de suivi avec les journaux de livraison et l'adresse du destinataire.

Parametres du chemin
ParametreTypeRequisDescription
idinteger*L'ID de commande retourne lors de la creation
Exemple de requete
curl https://server.shipper.network/api/v1/orders/555 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
Reponse

200

{
  "id": 555,
  "status": "Paid",
  "contact_task_status": "called",
  "shipments": [
    {
      "uuid": "11111111-2222-3333-4444-555555555555",
      "status": "delivered",
      "tracking_numbers": [
        {
          "number": "99999999999",
          "logs": [
            { "status": "at_carrier_origin_facility", "created_at": "2025-01-15T02:02:59.000000Z", "external_timestamp": "2025-01-14 22:48:00" },
            { "status": "in_transit", "created_at": "2025-01-15T02:02:59.000000Z", "external_timestamp": "2025-01-14 23:05:00" },
            { "status": "delivered", "created_at": "2025-01-18T02:09:19.000000Z", "external_timestamp": "2025-01-17 14:16:00" }
          ]
        }
      ]
    }
  ],
  "address": {
    "first_name": "Omar", "last_name": "Ben Ali",
    "phone1": "+21628177188", "phone2": "",
    "address1": "Rue de la Liberte", "address2": "",
    "division_1": "Tunis", "division_2": null, "country": "TN"
  }
}

POSTPOST /orders/{id}/cancel

Annule une commande et ses expeditions associees. Fonctionne pour les commandes en phase de confirmation (en attente de confirmation telephonique) ou en phase de preparation (en attente d'emballage). Les commandes deja expediees ne peuvent pas etre annulees via l'API.

Parametres du chemin
ParametreTypeRequisDescription
idinteger*L'ID de la commande a annuler
Exemple de requete
curl -X POST https://server.shipper.network/api/v1/orders/555/cancel \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
Reponse

200

{
  "success": true,
  "canceled_shipments": 1
}
Reponse d'erreur

422Si aucune expedition ne peut etre annulee :

{
  "error": "No shipments available to cancel"
}

Webhooks

Les webhooks vous permettent de recevoir des notifications HTTP en temps reel lors des changements de statut, au lieu d'interroger l'API.

POSTPOST /webhooks

Enregistrez une URL pour recevoir les evenements webhook. Vous pouvez enregistrer jusqu'a 5 webhooks par cle API. L'URL doit utiliser HTTPS.

Corps de la requete
ParametreTypeRequisDescription
urlstring*URL HTTPS qui recevra les requetes POST avec les donnees d'evenement
eventsarray*Evenements : "order.status_changed" et/ou "shipment.status_changed"
secretstring-Cle secrete (min 16 caracteres) utilisee pour signer les donnees avec HMAC-SHA256
Exemple de requete
curl -X POST https://server.shipper.network/api/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://mystore.com/webhooks/shipper",
    "events": ["order.status_changed", "shipment.status_changed"],
    "secret": "my-webhook-secret-key"
  }'
Reponse

201

{
  "id": 1,
  "url": "https://mystore.com/webhooks/shipper",
  "events": ["order.status_changed", "shipment.status_changed"],
  "status": "active",
  "created_at": "2025-03-29T10:00:00.000000Z"
}

GETGET /webhooks

Retourne tous les webhooks enregistres pour la cle API actuelle, incluant leur statut et le nombre d'echecs.

Exemple de requete
curl https://server.shipper.network/api/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
Reponse

200

[
  {
    "id": 1,
    "url": "https://mystore.com/webhooks/shipper",
    "events": ["order.status_changed", "shipment.status_changed"],
    "status": "active",
    "last_triggered_at": "2025-03-29T15:30:00.000000Z",
    "failure_count": 0,
    "created_at": "2025-03-29T10:00:00.000000Z"
  }
]

DELETEDELETE /webhooks/{id}

Supprime un enregistrement webhook. Le webhook cessera de recevoir les evenements immediatement.

Exemple de requete
curl -X DELETE https://server.shipper.network/api/v1/webhooks/1 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
Reponse

200

{ "success": true }

Format du contenu Webhook

Lorsqu'un evenement se produit, Shipper envoie une requete POST a votre URL enregistree avec un corps JSON :

order.status_changed
{
  "event": "order.status_changed",
  "timestamp": "2025-01-15T10:30:00.000000Z",
  "data": {
    "order_id": 555,
    "status": "Paid",
    "previous_status": "Pending"
  }
}
shipment.status_changed
{
  "event": "shipment.status_changed",
  "timestamp": "2025-01-15T10:30:00.000000Z",
  "data": {
    "order_id": 555,
    "shipment_uuid": "11111111-2222-3333-4444-555555555555",
    "status": "delivered",
    "previous_status": "onitsway"
  }
}
Verification de la signature

Si vous avez fourni un secret lors de l'enregistrement, chaque requete inclut un en-tete X-Shipper-Signature. Verifiez-le en calculant le HMAC-SHA256 du corps brut avec votre secret :

// Node.js example
const crypto = require('crypto');
const signature = crypto.createHmac('sha256', 'my-webhook-secret-key')
  .update(rawBody)
  .digest('hex');
const isValid = signature === req.headers['x-shipper-signature'];

Codes d'erreur

L'API utilise les codes de statut HTTP standards. Toutes les reponses d'erreur incluent un corps JSON avec les details.

CodeSignification
200Succes
201Ressource creee avec succes
401Non autorise - cle API manquante ou invalide
403Interdit - cle API desactivee ou revoquee
404Non trouve - la ressource demandee n'existe pas
422Erreur de validation - verifiez l'objet errors dans le corps de la reponse
429Trop de requetes - limite de debit depassee. Attendez et reessayez