Integrez votre systeme avec Shipper pour creer et suivre les commandes automatiquement.
L'Open API Shipper est une API REST qui vous permet de :
https://server.shipper.network/api/v1Pour commencer, generez une cle API depuis votre tableau de bord Shipperdans Integrations > API.
Toutes les requetes API necessitent un token Bearer dans l'en-tete Authorization.
Authorization: Bearer YOUR_API_KEY
Accept: application/json
Content-Type: application/jsonLes requetes sont limitees par cle API. Depasser la limite retourne HTTP 429 (Too Many Requests).
| Type de point d'acces | Limite | Points d'acces |
|---|---|---|
| Lecture | 120req/min | GET /products, /orders, /orders/:id, /webhooks |
| Reference | 60req/min | GET /countries, /countries/:code/divisions |
| Ecriture | 30req/min | POST /orders, /webhooks |
| Destructif | 20req/min | POST /orders/:id/cancel, DELETE /webhooks/:id |
Les en-tetes de limite (X-RateLimit-Limit, X-RateLimit-Remaining) sont inclus dans chaque reponse.
GET /countriesRetourne tous les pays supportes avec leur structure geographique. Utilisez ceci pour comprendre quels niveaux de division (gouvernorat, delegation, etc.) sont requis pour chaque pays.
curl https://server.shipper.network/api/v1/countries \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"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.
GET /countries/{code}/divisionsRetourne 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.
| Parametre | Type | Requis | Description |
|---|---|---|---|
level | integer | - | Niveau de division (defaut : 1 = niveau superieur) |
parent_id | integer | - | Filtrer par ID de division parente pour obtenir les enfants |
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 }
]
}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 }
]
}GET /productsRetourne votre catalogue produits avec les UUIDs. Vous avez besoin des UUIDs pour creer des commandes via l'API.
| Parametre | Type | Requis | Description |
|---|---|---|---|
page | integer | - | Numero de page (defaut : 1) |
per_page | integer | - | Elements par page (defaut : 20, max : 100) |
search | string | - | Rechercher par nom de produit ou SKU |
curl "https://server.shipper.network/api/v1/products?per_page=10&search=shirt" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"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 }
}GET /products/{uuid}Retourne un produit par UUID, incluant ses variantes et les quantites disponibles en stock.
curl https://server.shipper.network/api/v1/products/2e97b37a-3118-4905-842c-19706bcf1455 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"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 }
]
}GET /ordersRetourne une liste paginee de vos commandes. Utilisez les filtres pour affiner par statut, plage de dates ou termes de recherche.
| Parametre | Type | Requis | Description |
|---|---|---|---|
page | integer | - | Numero de page (defaut : 1) |
per_page | integer | - | Elements par page (defaut : 20, max : 100) |
status | string | - | Filtrer par statut d'expedition (ex: delivered, awaitingpackaging, canceled) |
start_date | string | - | Filtrer les commandes creees a partir de cette date (AAAA-MM-JJ) |
end_date | string | - | Filtrer les commandes creees jusqu'a cette date (AAAA-MM-JJ) |
search | string | - | Rechercher par ID de commande, nom du client ou numero de telephone |
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"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 }
}POST /ordersCree une nouvelle commande dans Shipper. Retourne l'ID de commande que vous pouvez utiliser pour suivre la commande.
| Parametre | Type | Requis | Description |
|---|---|---|---|
address | object | * | Objet adresse du destinataire (voir les champs ci-dessous) |
address.name | string | * | Nom complet - separe automatiquement en prenom et nom |
address.phone1 | string | * | Numero de telephone principal |
address.phone2 | string | - | Numero de telephone secondaire |
address.address1 | string | * | Adresse ligne 1 |
address.address2 | string | - | Adresse ligne 2 |
address.division_1 | string | - | Etat / Gouvernorat - utilisez le nom exact de GET /countries/{code}/divisions |
address.division_2 | string | - | Ville / Delegation - utilisez le nom exact de GET /countries/{code}/divisions?level=2&parent_id=... |
address.country | string | * | Code pays a deux lettres (ex: TN, DZ, MA) |
items | array | * | Tableau des articles de la commande |
items[].id | string | * | UUID du produit ou de la variante de GET /products |
items[].quantity | integer | - | Quantite (defaut : 1) |
items[].total_price | number | - | Prix total pour cette ligne. Par defaut : prix du produit x quantite |
shipping_total | number | - | Frais de livraison factures au client (defaut : 0) |
is_cod | boolean | - | ) |
auto_fulfill | boolean | - | Envoyer directement en preparation sans creer de brouillon (defaut : false) |
with_confirmation | boolean | - | Exiger un appel de confirmation avant l'expedition (defaut : false) |
store_name | string | - | Nom du magasin source - apparait dans le suivi pour votre reference |
external_order_id | string | - | ID de reference de votre systeme - affiche dans le tableau de bord Shipper |
external_order_url | string | - | URL de la commande dans votre systeme - cliquable depuis le tableau de bord Shipper |
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"
}'201Cree
{
"id": 555
}GET /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.
| Parametre | Type | Requis | Description |
|---|---|---|---|
id | integer | * | L'ID de commande retourne lors de la creation |
curl https://server.shipper.network/api/v1/orders/555 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"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"
}
}POST /orders/{id}/cancelAnnule 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.
| Parametre | Type | Requis | Description |
|---|---|---|---|
id | integer | * | L'ID de la commande a annuler |
curl -X POST https://server.shipper.network/api/v1/orders/555/cancel \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"200
{
"success": true,
"canceled_shipments": 1
}422Si aucune expedition ne peut etre annulee :
{
"error": "No shipments available to cancel"
}Les webhooks vous permettent de recevoir des notifications HTTP en temps reel lors des changements de statut, au lieu d'interroger l'API.
POST /webhooksEnregistrez une URL pour recevoir les evenements webhook. Vous pouvez enregistrer jusqu'a 5 webhooks par cle API. L'URL doit utiliser HTTPS.
| Parametre | Type | Requis | Description |
|---|---|---|---|
url | string | * | URL HTTPS qui recevra les requetes POST avec les donnees d'evenement |
events | array | * | Evenements : "order.status_changed" et/ou "shipment.status_changed" |
secret | string | - | Cle secrete (min 16 caracteres) utilisee pour signer les donnees avec HMAC-SHA256 |
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"
}'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"
}GET /webhooksRetourne tous les webhooks enregistres pour la cle API actuelle, incluant leur statut et le nombre d'echecs.
curl https://server.shipper.network/api/v1/webhooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"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"
}
]DELETE /webhooks/{id}Supprime un enregistrement webhook. Le webhook cessera de recevoir les evenements immediatement.
curl -X DELETE https://server.shipper.network/api/v1/webhooks/1 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"200
{ "success": true }Lorsqu'un evenement se produit, Shipper envoie une requete POST a votre URL enregistree avec un corps JSON :
{
"event": "order.status_changed",
"timestamp": "2025-01-15T10:30:00.000000Z",
"data": {
"order_id": 555,
"status": "Paid",
"previous_status": "Pending"
}
}{
"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"
}
}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'];L'API utilise les codes de statut HTTP standards. Toutes les reponses d'erreur incluent un corps JSON avec les details.
| Code | Signification |
|---|---|
| 200 | Succes |
| 201 | Ressource creee avec succes |
| 401 | Non autorise - cle API manquante ou invalide |
| 403 | Interdit - cle API desactivee ou revoquee |
| 404 | Non trouve - la ressource demandee n'existe pas |
| 422 | Erreur de validation - verifiez l'objet errors dans le corps de la reponse |
| 429 | Trop de requetes - limite de debit depassee. Attendez et reessayez |