Introduction
SOO API est une API REST de gestion logistique et douanière pour les entreprises d'import/export en Afrique de l'Ouest.
Elle fournit :
- Gestion douanière — dossiers d'import/export/transit avec cycle de statuts
- Expéditions — suivi maritime/aérien/routier/ferroviaire avec tracking en temps réel
- Facturation — factures internes, paiements, validation et envoi
- Documents — gestion centralisée polymorphe de pièces jointes
- Import / Export — traitement asynchrone Excel/CSV via file d'attente
- Notifications — alertes in-app et par email sur les changements critiques
Format de réponse
Toutes les réponses API suivent une envelope standard {data, meta, links} :
{
"data": { ... },
"meta": { "success": true, "message": "Opération réussie." },
"links": {}
}
Codes HTTP
| Code | Signification |
|---|---|
| 200 | Succès |
| 201 | Création réussie |
| 400 | Requête invalide |
| 401 | Non authentifié |
| 403 | Permission insuffisante |
| 404 | Ressource introuvable |
| 422 | Erreur de validation |
| 500 | Erreur serveur |
Authentification
SOO API utilise un système double guard : JWT pour les sessions web/app et Sanctum pour les clés API programmatiques.
JWT (sessions web/app)
Authentifiez-vous via POST /api/v1/auth/login pour obtenir un access_token. Incluez ce token dans le header Authorization de chaque requête :
Authorization: Bearer {access_token}
Le token a une durée de vie de 60 minutes (configurable). Utilisez POST /api/v1/auth/refresh pour le renouveler.
Sanctum (clés API)
Pour les intégrations tierces, créez un token Sanctum via POST /api/v1/auth/tokens avec des abilities (permissions) spécifiques. Les tokens Sanctum sont longue durée.
Comptes de démonstration
| Mot de passe | Rôle | |
|---|---|---|
| admin@soo.com | password | Super Admin |
| client@soo.com | password | Client |
Authentification
Authentification JWT pour les clients web/app de SOO API.
Les endpoints permettent d'obtenir un jeton JWT (login), de le rafraîchir, de récupérer l'utilisateur courant et de se déconnecter.
Pour les intégrations externes (API keys longues durée), utilisez plutôt les
tokens Sanctum via /api/v1/auth/tokens.
Connexion (JWT).
Échange des identifiants contre un jeton JWT (access_token) + refresh_token.
Example request:
curl --request POST \
"http://localhost/api/v1/auth/login" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"admin@soo.com\",
\"password\": \"password\"
}"
const url = new URL(
"http://localhost/api/v1/auth/login"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "admin@soo.com",
"password": "password"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"data": {
"access_token": "eyJ...",
"token_type": "bearer",
"expires_in": 3600,
"user": {
"id": 1,
"name": "Super Admin",
"email": "admin@soo.com",
"roles": [
"Super Admin"
]
}
},
"meta": {
"success": true
},
"links": {}
}
Example response (422):
{
"data": null,
"meta": {
"success": false,
"message": "Identifiants invalides.",
"code": 422
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Profil courant.
requires authentication
Renvoie l'utilisateur authentifié par le jeton JWT.
Example request:
curl --request GET \
--get "http://localhost/api/v1/auth/me" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/auth/me"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{"data":{"id":1,"name":"Super Admin","email":"admin@soo.com","roles":["Super Admin"],"permissions":["access_users",...]},"meta":{"success":true},"links":{}}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Rafraîchir le jeton JWT.
requires authentication
Génère un nouveau jeton à partir du jeton courant (avant expiration).
Example request:
curl --request POST \
"http://localhost/api/v1/auth/refresh" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/auth/refresh"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"access_token": "eyJ...",
"token_type": "bearer",
"expires_in": 3600
},
"meta": {
"success": true
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Déconnexion (JWT).
requires authentication
Invalide le jeton courant.
Example request:
curl --request POST \
"http://localhost/api/v1/auth/logout" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/auth/logout"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200):
{
"data": null,
"meta": {
"success": true,
"message": "Déconnexion réussie."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Changer le mot de passe de l'utilisateur courant.
requires authentication
Example request:
curl --request PUT \
"http://localhost/api/v1/auth/password" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"current_password\": \"password\",
\"password\": \"newpassword\",
\"password_confirmation\": \"newpassword\"
}"
const url = new URL(
"http://localhost/api/v1/auth/password"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"current_password": "password",
"password": "newpassword",
"password_confirmation": "newpassword"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"data": null,
"meta": {
"success": true,
"message": "Mot de passe mis à jour."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Créer un token API Sanctum (longue durée).
requires authentication
Pour les intégrations externes. Le token est affiché une seule fois.
Example request:
curl --request POST \
"http://localhost/api/v1/auth/tokens" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Integration ERP\",
\"abilities\": [
\"douane:read\",
\"expedition:read\"
]
}"
const url = new URL(
"http://localhost/api/v1/auth/tokens"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Integration ERP",
"abilities": [
"douane:read",
"expedition:read"
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"data": {
"token": "1|abcdef...",
"name": "Integration ERP",
"abilities": [
"*"
]
},
"meta": {
"success": true,
"message": "Token créé."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Lister les tokens API Sanctum de l'utilisateur courant.
requires authentication
Example request:
curl --request GET \
--get "http://localhost/api/v1/auth/tokens" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/auth/tokens"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"id": 1,
"name": "Integration ERP",
"abilities": [
"*"
],
"last_used_at": "2026-07-06T12:00:00Z",
"created_at": "2026-07-06T10:00:00Z"
}
],
"meta": {
"success": true
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Révoquer un token API Sanctum.
requires authentication
Example request:
curl --request DELETE \
"http://localhost/api/v1/auth/tokens/1" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/auth/tokens/1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (200):
{
"data": null,
"meta": {
"success": true,
"message": "Token révoqué."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Clients
Gestion des clients SOO (comptes clients optionnels, activés par un admin).
Lister les clients (paginé).
Example request:
curl --request GET \
--get "http://localhost/api/v1/clients?search=DEMO&is_active=1&per_page=20" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/clients"
);
const params = {
"search": "DEMO",
"is_active": "1",
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"id": 1,
"name": "Client Démo",
"code": "DEMO-001",
"email": "demo@client.com",
"is_active": true,
"users_count": 1
}
],
"meta": {
"success": true,
"pagination": {
"total": 1,
"count": 1,
"per_page": 15,
"current_page": 1,
"last_page": 1
}
},
"links": {
"first": null,
"last": null,
"prev": null,
"next": null
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Créer un client.
Example request:
curl --request POST \
"http://localhost/api/v1/clients" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"ACME Logistique\",
\"code\": \"ACME-001\",
\"email\": \"contact@acme.com\",
\"phone\": \"+225 00 00 00 00\",
\"address\": \"Abidjan\",
\"is_active\": false
}"
const url = new URL(
"http://localhost/api/v1/clients"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "ACME Logistique",
"code": "ACME-001",
"email": "contact@acme.com",
"phone": "+225 00 00 00 00",
"address": "Abidjan",
"is_active": false
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"data": {
"id": 2,
"name": "ACME Logistique",
"code": "ACME-001",
"email": "contact@acme.com",
"is_active": true
},
"meta": {
"success": true,
"message": "Client créé."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Afficher un client (avec ses utilisateurs).
Example request:
curl --request GET \
--get "http://localhost/api/v1/clients/1" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/clients/1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"name": "Client Démo",
"code": "DEMO-001",
"email": "demo@client.com",
"is_active": true,
"users": [
{
"id": 2,
"name": "Utilisateur Client",
"email": "client@soo.com"
}
]
},
"meta": {
"success": true
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mettre à jour un client.
Example request:
curl --request PUT \
"http://localhost/api/v1/clients/1" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"architecto\",
\"code\": \"architecto\",
\"email\": \"gbailey@example.net\",
\"phone\": \"architecto\",
\"address\": \"architecto\",
\"is_active\": false
}"
const url = new URL(
"http://localhost/api/v1/clients/1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "architecto",
"code": "architecto",
"email": "gbailey@example.net",
"phone": "architecto",
"address": "architecto",
"is_active": false
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"name": "Client Démo",
"code": "DEMO-001",
"is_active": true
},
"meta": {
"success": true,
"message": "Client mis à jour."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Supprimer un client.
Example request:
curl --request DELETE \
"http://localhost/api/v1/clients/1" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/clients/1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (200):
{
"data": null,
"meta": {
"success": true,
"message": "Client supprimé."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Activer/désactiver un client.
Example request:
curl --request POST \
"http://localhost/api/v1/clients/1/toggle-active" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"is_active\": false
}"
const url = new URL(
"http://localhost/api/v1/clients/1/toggle-active"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"is_active": false
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"is_active": true
},
"meta": {
"success": true,
"message": "Statut du client mis à jour."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Documents
Gestion centralisée des documents SOO (customs, shipping, invoices, contracts).
Les documents sont polymorphes : ils peuvent être attachés à n'importe quelle
entité (Douane, Expédition, Facture, Client, etc.) via documentable_type +
documentable_id.
Lister les documents (paginé, filtrable par type et entité).
Example request:
curl --request GET \
--get "http://localhost/api/v1/documents?type=invoice&documentable_type=Modules%5CUserManagement%5CModels%5CClient&documentable_id=1&search=BL&per_page=20" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/documents"
);
const params = {
"type": "invoice",
"documentable_type": "Modules\UserManagement\Models\Client",
"documentable_id": "1",
"search": "BL",
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"id": 1,
"name": "BL-001.pdf",
"type": "shipping",
"mime_type": "application/pdf",
"size": 1024,
"uploaded_by": 1,
"created_at": "2026-07-06T12:00:00Z"
}
],
"meta": {
"success": true,
"pagination": {
"total": 1,
"count": 1,
"per_page": 15,
"current_page": 1,
"last_page": 1
}
},
"links": {
"first": null,
"last": null,
"prev": null,
"next": null
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Uploader un document.
Le fichier est envoyé en multipart/form-data. Optionnellement attaché à
une entité via documentable_type + documentable_id.
Example request:
curl --request POST \
"http://localhost/api/v1/documents" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "type=shipping"\
--form "description=Eius et animi quos velit et."\
--form "documentable_type=Modules\UserManagement\Models\Client"\
--form "documentable_id=1"\
--form "file=@/tmp/phpjkgn6vbjlmh72k2ThPB" const url = new URL(
"http://localhost/api/v1/documents"
);
const headers = {
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('type', 'shipping');
body.append('description', 'Eius et animi quos velit et.');
body.append('documentable_type', 'Modules\UserManagement\Models\Client');
body.append('documentable_id', '1');
body.append('file', document.querySelector('input[name="file"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());Example response (201):
{
"data": {
"id": 1,
"name": "BL-001.pdf",
"type": "shipping",
"mime_type": "application/pdf",
"size": 1024,
"path": "documents/2026/07/BL-001.pdf",
"uploaded_by": 1
},
"meta": {
"success": true,
"message": "Document uploadé."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Afficher un document.
Example request:
curl --request GET \
--get "http://localhost/api/v1/documents/16" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/documents/16"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"name": "BL-001.pdf",
"type": "shipping",
"mime_type": "application/pdf",
"size": 1024,
"path": "documents/2026/07/BL-001.pdf",
"uploaded_by": 1,
"description": null,
"created_at": "2026-07-06T12:00:00Z"
},
"meta": {
"success": true
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mettre à jour les métadonnées d'un document (pas le fichier lui-même).
Example request:
curl --request PUT \
"http://localhost/api/v1/documents/16" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"architecto\",
\"type\": \"architecto\",
\"description\": \"Eius et animi quos velit et.\"
}"
const url = new URL(
"http://localhost/api/v1/documents/16"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "architecto",
"type": "architecto",
"description": "Eius et animi quos velit et."
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"name": "BL-001-renamed.pdf",
"type": "shipping"
},
"meta": {
"success": true,
"message": "Document mis à jour."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Supprimer un document.
Example request:
curl --request DELETE \
"http://localhost/api/v1/documents/16" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/documents/16"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (200):
{
"data": null,
"meta": {
"success": true,
"message": "Document supprimé."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Télécharger un document.
Example request:
curl --request GET \
--get "http://localhost/api/v1/documents/16/download" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/documents/16/download"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
binary
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Douane
Gestion des dossiers douaniers (import/export/transit).
Chaque dossier passe par un cycle de statuts :
draft → submitted → in_review → approved / rejected → cleared
Lister les dossiers douaniers (paginé, filtrable).
Example request:
curl --request GET \
--get "http://localhost/api/v1/dossiers-douane?status=approved&type=import&client_id=1&search=DD-2026&per_page=20" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/dossiers-douane"
);
const params = {
"status": "approved",
"type": "import",
"client_id": "1",
"search": "DD-2026",
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"id": 1,
"reference": "DD-2026-000001",
"type": "import",
"status": "draft",
"goods_description": "Conteneurs de café",
"goods_value": "5000000.00",
"currency": "XAF",
"weight_kg": "12000.00",
"client": {
"id": 1,
"name": "Client Démo"
},
"created_at": "2026-07-06T12:00:00Z"
}
],
"meta": {
"success": true,
"pagination": {
"total": 1,
"count": 1,
"per_page": 15,
"current_page": 1,
"last_page": 1
}
},
"links": {
"first": null,
"last": null,
"prev": null,
"next": null
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Créer un dossier douanier.
Example request:
curl --request POST \
"http://localhost/api/v1/dossiers-douane" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"type\": \"import\",
\"client_id\": 1,
\"origin_country\": \"Côte d\'Ivoire\",
\"destination_country\": \"France\",
\"goods_description\": \"Conteneurs de café\",
\"goods_value\": 5000000,
\"currency\": \"XAF\",
\"weight_kg\": 12000,
\"containers\": [
\"MSCU1234567\",
\"MSCU8910111\"
],
\"notes\": \"architecto\"
}"
const url = new URL(
"http://localhost/api/v1/dossiers-douane"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"type": "import",
"client_id": 1,
"origin_country": "Côte d'Ivoire",
"destination_country": "France",
"goods_description": "Conteneurs de café",
"goods_value": 5000000,
"currency": "XAF",
"weight_kg": 12000,
"containers": [
"MSCU1234567",
"MSCU8910111"
],
"notes": "architecto"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"data": {
"id": 1,
"reference": "DD-2026-000001",
"type": "import",
"status": "draft",
"goods_description": "Conteneurs de café"
},
"meta": {
"success": true,
"message": "Dossier créé."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Afficher un dossier douanier (avec documents).
Example request:
curl --request GET \
--get "http://localhost/api/v1/dossiers-douane/1" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/dossiers-douane/1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"reference": "DD-2026-000001",
"type": "import",
"status": "draft",
"documents": [],
"client": {
"id": 1,
"name": "Client Démo"
}
},
"meta": {
"success": true
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mettre à jour un dossier douanier.
Example request:
curl --request PUT \
"http://localhost/api/v1/dossiers-douane/1" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"client_id\": 16,
\"origin_country\": \"n\",
\"destination_country\": \"g\",
\"goods_description\": \"z\",
\"goods_value\": 77,
\"currency\": \"iyv\",
\"weight_kg\": 42,
\"containers\": [
\"l\"
],
\"notes\": \"j\"
}"
const url = new URL(
"http://localhost/api/v1/dossiers-douane/1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"client_id": 16,
"origin_country": "n",
"destination_country": "g",
"goods_description": "z",
"goods_value": 77,
"currency": "iyv",
"weight_kg": 42,
"containers": [
"l"
],
"notes": "j"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"reference": "DD-2026-000001",
"status": "draft"
},
"meta": {
"success": true,
"message": "Dossier mis à jour."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Supprimer un dossier douanier (uniquement si brouillon).
Example request:
curl --request DELETE \
"http://localhost/api/v1/dossiers-douane/1" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/dossiers-douane/1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (200):
{
"data": null,
"meta": {
"success": true,
"message": "Dossier supprimé."
},
"links": {}
}
Example response (422):
{
"data": null,
"meta": {
"success": false,
"message": "Seuls les dossiers en brouillon peuvent être supprimés.",
"code": 422
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Changer le statut d'un dossier douanier.
Example request:
curl --request POST \
"http://localhost/api/v1/dossiers-douane/1/status" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"status\": \"submitted\",
\"notes\": \"architecto\"
}"
const url = new URL(
"http://localhost/api/v1/dossiers-douane/1/status"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"status": "submitted",
"notes": "architecto"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"reference": "DD-2026-000001",
"status": "submitted",
"submitted_at": "2026-07-06T13:00:00Z"
},
"meta": {
"success": true,
"message": "Statut mis à jour."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Endpoints
GET api/v1
Example request:
curl --request GET \
--get "http://localhost/api/v1" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"data": {
"name": "SOO API",
"version": "v1",
"status": "ok"
},
"meta": {
"success": true,
"message": "SOO API v1 is running."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
GET api/v1/tracking/{reference}
Example request:
curl --request GET \
--get "http://localhost/api/v1/tracking/architecto" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/tracking/architecto"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (401):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"data": null,
"meta": {
"success": false,
"message": "Non authentifié.",
"code": 401
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Expédition
Gestion des expéditions (maritime, aérien, routier, ferroviaire) avec suivi par étapes.
Cycle de statuts : pending → in_transit → at_port → customs → delivered
(ou cancelled à tout moment).
Lister les expéditions (paginé, filtrable).
Example request:
curl --request GET \
--get "http://localhost/api/v1/expeditions?status=in_transit&type=sea&client_id=1&search=EXP-2026&per_page=20" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/expeditions"
);
const params = {
"status": "in_transit",
"type": "sea",
"client_id": "1",
"search": "EXP-2026",
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"id": 1,
"reference": "EXP-2026-000001",
"type": "sea",
"status": "pending",
"origin": "Abidjan",
"destination": "Le Havre",
"carrier": "Maersk",
"tracking_number": "MAEU123456"
}
],
"meta": {
"success": true,
"pagination": {
"total": 1,
"count": 1,
"per_page": 15,
"current_page": 1,
"last_page": 1
}
},
"links": {
"first": null,
"last": null,
"prev": null,
"next": null
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Créer une expédition.
Example request:
curl --request POST \
"http://localhost/api/v1/expeditions" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"type\": \"sea\",
\"client_id\": 1,
\"origin\": \"Abidjan\",
\"destination\": \"Le Havre\",
\"carrier\": \"Maersk\",
\"tracking_number\": \"MAEU123456\",
\"container_number\": \"MSCU1234567\",
\"bill_of_lading\": \"BL-2026-001\",
\"estimated_departure\": \"2026-08-01T08:00:00Z\",
\"estimated_arrival\": \"2026-08-20T08:00:00Z\",
\"notes\": \"architecto\"
}"
const url = new URL(
"http://localhost/api/v1/expeditions"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"type": "sea",
"client_id": 1,
"origin": "Abidjan",
"destination": "Le Havre",
"carrier": "Maersk",
"tracking_number": "MAEU123456",
"container_number": "MSCU1234567",
"bill_of_lading": "BL-2026-001",
"estimated_departure": "2026-08-01T08:00:00Z",
"estimated_arrival": "2026-08-20T08:00:00Z",
"notes": "architecto"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"data": {
"id": 1,
"reference": "EXP-2026-000001",
"status": "pending"
},
"meta": {
"success": true,
"message": "Expédition créée."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Afficher une expédition (avec suivi et documents).
Example request:
curl --request GET \
--get "http://localhost/api/v1/expeditions/1" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/expeditions/1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"reference": "EXP-2026-000001",
"status": "pending",
"tracking_steps": [
{
"status": "pending",
"location": "Abidjan",
"description": "Expédition créée",
"occurred_at": "2026-07-06T12:00:00Z"
}
],
"documents": []
},
"meta": {
"success": true
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mettre à jour une expédition.
Example request:
curl --request PUT \
"http://localhost/api/v1/expeditions/1" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"client_id\": 16,
\"origin\": \"n\",
\"destination\": \"g\",
\"carrier\": \"z\",
\"tracking_number\": \"m\",
\"container_number\": \"i\",
\"bill_of_lading\": \"y\",
\"estimated_departure\": \"2026-07-06T21:38:49\",
\"actual_departure\": \"2026-07-06T21:38:49\",
\"estimated_arrival\": \"2026-07-06T21:38:49\",
\"actual_arrival\": \"2026-07-06T21:38:49\",
\"notes\": \"v\"
}"
const url = new URL(
"http://localhost/api/v1/expeditions/1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"client_id": 16,
"origin": "n",
"destination": "g",
"carrier": "z",
"tracking_number": "m",
"container_number": "i",
"bill_of_lading": "y",
"estimated_departure": "2026-07-06T21:38:49",
"actual_departure": "2026-07-06T21:38:49",
"estimated_arrival": "2026-07-06T21:38:49",
"actual_arrival": "2026-07-06T21:38:49",
"notes": "v"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"reference": "EXP-2026-000001"
},
"meta": {
"success": true,
"message": "Expédition mise à jour."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Supprimer une expédition (uniquement si en attente).
Example request:
curl --request DELETE \
"http://localhost/api/v1/expeditions/1" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/expeditions/1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (200):
{
"data": null,
"meta": {
"success": true,
"message": "Expédition supprimée."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mettre à jour le statut d'une expédition (crée une étape de suivi).
Example request:
curl --request POST \
"http://localhost/api/v1/expeditions/1/status" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"status\": \"in_transit\",
\"location\": \"Port d\'Abidjan\",
\"description\": \"Conteneur chargé sur le navire\",
\"occurred_at\": \"2026-08-01T10:00:00Z\"
}"
const url = new URL(
"http://localhost/api/v1/expeditions/1/status"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"status": "in_transit",
"location": "Port d'Abidjan",
"description": "Conteneur chargé sur le navire",
"occurred_at": "2026-08-01T10:00:00Z"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"reference": "EXP-2026-000001",
"status": "in_transit",
"actual_departure": "2026-08-01T10:00:00Z"
},
"meta": {
"success": true,
"message": "Statut mis à jour."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Facturation
Gestion des factures internes et paiements.
Cycle de statuts : draft → sent → paid / partially_paid / overdue / cancelled
Les factures doivent être validées avant envoi. Les paiements sont enregistrés séparément et mettent à jour automatiquement le statut de la facture.
Lister les factures (paginé, filtrable).
Example request:
curl --request GET \
--get "http://localhost/api/v1/factures?status=sent&client_id=1&search=FAC-2026&per_page=20" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/factures"
);
const params = {
"status": "sent",
"client_id": "1",
"search": "FAC-2026",
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"id": 1,
"reference": "FAC-2026-000001",
"status": "draft",
"total": "5500000.00",
"currency": "XAF",
"client": {
"id": 1,
"name": "Client Démo"
}
}
],
"meta": {
"success": true,
"pagination": {
"total": 1,
"count": 1,
"per_page": 15,
"current_page": 1,
"last_page": 1
}
},
"links": {
"first": null,
"last": null,
"prev": null,
"next": null
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Créer une facture (brouillon).
Example request:
curl --request POST \
"http://localhost/api/v1/factures" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"client_id\": 1,
\"expedition_id\": 1,
\"dossier_douane_id\": 1,
\"issue_date\": \"2026-07-06\",
\"due_date\": \"2026-08-06\",
\"subtotal\": 5000000,
\"tax_rate\": 18,
\"discount\": 0,
\"currency\": \"XAF\",
\"items\": [
\"architecto\"
],
\"notes\": \"architecto\"
}"
const url = new URL(
"http://localhost/api/v1/factures"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"client_id": 1,
"expedition_id": 1,
"dossier_douane_id": 1,
"issue_date": "2026-07-06",
"due_date": "2026-08-06",
"subtotal": 5000000,
"tax_rate": 18,
"discount": 0,
"currency": "XAF",
"items": [
"architecto"
],
"notes": "architecto"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"data": {
"id": 1,
"reference": "FAC-2026-000001",
"status": "draft",
"total": "5900000.00"
},
"meta": {
"success": true,
"message": "Facture créée."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Afficher une facture (avec paiements et documents).
Example request:
curl --request GET \
--get "http://localhost/api/v1/factures/1" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/factures/1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"reference": "FAC-2026-000001",
"status": "draft",
"items": [],
"payments": [],
"documents": []
},
"meta": {
"success": true
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mettre à jour une facture (uniquement si brouillon).
Example request:
curl --request PUT \
"http://localhost/api/v1/factures/1" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"client_id\": 16,
\"expedition_id\": 16,
\"dossier_douane_id\": 16,
\"issue_date\": \"2026-07-06T21:38:49\",
\"due_date\": \"2052-07-29\",
\"subtotal\": 39,
\"tax_rate\": 7,
\"discount\": 12,
\"currency\": \"miy\",
\"notes\": \"v\",
\"items\": [
{
\"description\": \"Eius et animi quos velit et.\",
\"quantity\": 60,
\"unit_price\": 42
}
]
}"
const url = new URL(
"http://localhost/api/v1/factures/1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"client_id": 16,
"expedition_id": 16,
"dossier_douane_id": 16,
"issue_date": "2026-07-06T21:38:49",
"due_date": "2052-07-29",
"subtotal": 39,
"tax_rate": 7,
"discount": 12,
"currency": "miy",
"notes": "v",
"items": [
{
"description": "Eius et animi quos velit et.",
"quantity": 60,
"unit_price": 42
}
]
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"reference": "FAC-2026-000001",
"status": "draft"
},
"meta": {
"success": true,
"message": "Facture mise à jour."
},
"links": {}
}
Example response (422):
{
"data": null,
"meta": {
"success": false,
"message": "Seules les factures en brouillon peuvent être modifiées.",
"code": 422
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Supprimer une facture (uniquement si brouillon non validée).
Example request:
curl --request DELETE \
"http://localhost/api/v1/factures/1" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/factures/1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (200):
{
"data": null,
"meta": {
"success": true,
"message": "Facture supprimée."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Valider une facture (verrouille les montants, permet l'envoi).
Example request:
curl --request POST \
"http://localhost/api/v1/factures/1/validate" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/factures/1/validate"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"reference": "FAC-2026-000001",
"status": "draft",
"validated_at": "2026-07-06T13:00:00Z"
},
"meta": {
"success": true,
"message": "Facture validée."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Envoyer une facture validée au client.
Example request:
curl --request POST \
"http://localhost/api/v1/factures/1/send" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/factures/1/send"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"reference": "FAC-2026-000001",
"status": "sent"
},
"meta": {
"success": true,
"message": "Facture envoyée."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Enregistrer un paiement pour une facture.
Example request:
curl --request POST \
"http://localhost/api/v1/factures/1/payments" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"amount\": 3000000,
\"method\": \"bank_transfer\",
\"reference\": \"VIREMENT-001\",
\"paid_at\": \"2026-07-10\",
\"notes\": \"architecto\"
}"
const url = new URL(
"http://localhost/api/v1/factures/1/payments"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"amount": 3000000,
"method": "bank_transfer",
"reference": "VIREMENT-001",
"paid_at": "2026-07-10",
"notes": "architecto"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"reference": "FAC-2026-000001",
"status": "partially_paid",
"paid_amount": "3000000.00",
"total": "5900000.00"
},
"meta": {
"success": true,
"message": "Paiement enregistré."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Annuler une facture.
Example request:
curl --request POST \
"http://localhost/api/v1/factures/1/cancel" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/factures/1/cancel"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"reference": "FAC-2026-000001",
"status": "cancelled"
},
"meta": {
"success": true,
"message": "Facture annulée."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Import/Export
Gestion asynchrone des imports et exports Excel/CSV.
Les exports et imports sont traités en arrière-plan via des jobs queue.
Chaque opération est tracée dans la table imports_exports avec son statut,
le nombre de lignes traitées, et les erreurs éventuelles.
Modules supportés : douane, expedition, facturation
Lister les opérations import/export (paginé).
Example request:
curl --request GET \
--get "http://localhost/api/v1/imports-exports?type=export&module=douane&status=completed&per_page=15" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/imports-exports"
);
const params = {
"type": "export",
"module": "douane",
"status": "completed",
"per_page": "15",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"id": 1,
"reference": "EXP-2026-000001",
"type": "export",
"module": "douane",
"status": "completed",
"rows_total": 3,
"rows_success": 3,
"file_path": "exports/2026/07/douane_EXP-2026-000001_20260706.xlsx"
}
],
"meta": {
"success": true,
"pagination": {
"total": 1,
"count": 1,
"per_page": 15,
"current_page": 1,
"last_page": 1
}
},
"links": {
"first": null,
"last": null,
"prev": null,
"next": null
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Afficher une opération import/export.
Example request:
curl --request GET \
--get "http://localhost/api/v1/imports-exports/16" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/imports-exports/16"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"reference": "EXP-2026-000001",
"type": "export",
"module": "douane",
"status": "completed",
"rows_total": 3,
"rows_success": 3,
"errors": []
},
"meta": {
"success": true
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Lancer un export Excel/CSV (asynchrone).
Example request:
curl --request POST \
"http://localhost/api/v1/exports" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"module\": \"douane\",
\"format\": \"xlsx\",
\"filters\": {
\"status\": \"architecto\",
\"type\": \"architecto\",
\"client_id\": 16
}
}"
const url = new URL(
"http://localhost/api/v1/exports"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"module": "douane",
"format": "xlsx",
"filters": {
"status": "architecto",
"type": "architecto",
"client_id": 16
}
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"data": {
"id": 1,
"reference": "EXP-2026-000001",
"type": "export",
"module": "douane",
"status": "pending"
},
"meta": {
"success": true,
"message": "Export lancé. Vous recevrez une notification à la fin."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Uploader et lancer un import Excel/CSV (asynchrone).
Example request:
curl --request POST \
"http://localhost/api/v1/imports" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "module=douane"\
--form "file=@/tmp/phpnoeg9uajgpvm4x5YvgF" const url = new URL(
"http://localhost/api/v1/imports"
);
const headers = {
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('module', 'douane');
body.append('file', document.querySelector('input[name="file"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());Example response (201):
{
"data": {
"id": 2,
"reference": "IMP-2026-000001",
"type": "import",
"module": "douane",
"status": "pending",
"original_filename": "dossiers.xlsx"
},
"meta": {
"success": true,
"message": "Import lancé. Le traitement se fait en arrière-plan."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Télécharger le fichier d'un export terminé.
Example request:
curl --request GET \
--get "http://localhost/api/v1/imports-exports/16/download" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/imports-exports/16/download"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
binary
Example response (422):
{
"data": null,
"meta": {
"success": false,
"message": "Fichier non disponible.",
"code": 422
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Annuler une opération en attente ou en cours.
Example request:
curl --request POST \
"http://localhost/api/v1/imports-exports/16/cancel" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/imports-exports/16/cancel"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"reference": "EXP-2026-000001",
"status": "cancelled"
},
"meta": {
"success": true,
"message": "Opération annulée."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Télécharger un template Excel pour un module.
Example request:
curl --request GET \
--get "http://localhost/api/v1/import-templates/architecto?module=douane" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/import-templates/architecto"
);
const params = {
"module": "douane",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
binary
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Notifications
Notifications in-app SOO.
Les notifications sont créées automatiquement par les événements métier (changement de statut douanier, expédition, création/envoi/paiement de facture). Chaque utilisateur consulte ses propres notifications, marque comme lu ou supprime.
Lister les notifications de l'utilisateur connecté (paginé, filtrable).
Example request:
curl --request GET \
--get "http://localhost/api/v1/notifications?type=facture.created&unread=1&per_page=20" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/notifications"
);
const params = {
"type": "facture.created",
"unread": "1",
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"id": 1,
"type": "facture.created",
"title": "Nouvelle facture FAC-2026-000001",
"message": "La facture ... a été créée.",
"read_at": null,
"data": {
"reference": "FAC-2026-000001"
},
"created_at": "2026-07-06T12:00:00Z"
}
],
"meta": {
"success": true,
"pagination": {
"total": 1,
"count": 1,
"per_page": 15,
"current_page": 1,
"last_page": 1
}
},
"links": {
"first": null,
"last": null,
"prev": null,
"next": null
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Nombre de notifications non lues (pour badge).
Example request:
curl --request GET \
--get "http://localhost/api/v1/notifications/unread-count" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/notifications/unread-count"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"unread_count": 3
},
"meta": {
"success": true
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Marquer une notification comme lue.
Example request:
curl --request PATCH \
"http://localhost/api/v1/notifications/architecto/read" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/notifications/architecto/read"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "PATCH",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"read_at": "2026-07-06T13:00:00Z"
},
"meta": {
"success": true,
"message": "Notification marquée comme lue."
},
"links": {}
}
Example response (404):
{
"data": null,
"meta": {
"success": false,
"message": "Notification introuvable.",
"code": 404
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Marquer toutes les notifications comme lues.
Example request:
curl --request PATCH \
"http://localhost/api/v1/notifications/read-all" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/notifications/read-all"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "PATCH",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"marked_read": 5
},
"meta": {
"success": true,
"message": "Toutes les notifications ont été marquées comme lues."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Supprimer une notification.
Example request:
curl --request DELETE \
"http://localhost/api/v1/notifications/architecto" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/notifications/architecto"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (200):
{
"data": null,
"meta": {
"success": true,
"message": "Notification supprimée."
},
"links": {}
}
Example response (404):
{
"data": null,
"meta": {
"success": false,
"message": "Notification introuvable.",
"code": 404
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Utilisateurs
Gestion des utilisateurs SOO (admin only).
Lister les utilisateurs (paginé).
Example request:
curl --request GET \
--get "http://localhost/api/v1/users?search=admin&role=Op%C3%A9rateur&client_id=1&per_page=20&page=1" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/users"
);
const params = {
"search": "admin",
"role": "Opérateur",
"client_id": "1",
"per_page": "20",
"page": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"id": 1,
"name": "Super Admin",
"email": "admin@soo.com",
"is_active": true,
"roles": [
"Super Admin"
],
"client": null
}
],
"meta": {
"success": true,
"pagination": {
"total": 12,
"count": 12,
"per_page": 15,
"current_page": 1,
"last_page": 1
}
},
"links": {
"first": "http://...",
"last": null,
"prev": null,
"next": null
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Créer un utilisateur.
Example request:
curl --request POST \
"http://localhost/api/v1/users" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Jean Dupont\",
\"email\": \"jean@soo.com\",
\"password\": \"password\",
\"phone\": \"+225 00 00 00 00\",
\"client_id\": 1,
\"is_active\": true,
\"roles\": [
\"Opérateur\"
]
}"
const url = new URL(
"http://localhost/api/v1/users"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Jean Dupont",
"email": "jean@soo.com",
"password": "password",
"phone": "+225 00 00 00 00",
"client_id": 1,
"is_active": true,
"roles": [
"Opérateur"
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"data": {
"id": 13,
"name": "Jean Dupont",
"email": "jean@soo.com",
"is_active": true,
"roles": [
"Opérateur"
],
"client": null
},
"meta": {
"success": true,
"message": "Utilisateur créé."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Afficher un utilisateur.
Example request:
curl --request GET \
--get "http://localhost/api/v1/users/1" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/users/1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"name": "Super Admin",
"email": "admin@soo.com",
"is_active": true,
"roles": [
"Super Admin"
],
"client": null
},
"meta": {
"success": true
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mettre à jour un utilisateur.
Example request:
curl --request PUT \
"http://localhost/api/v1/users/1" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Jean Dupont\",
\"email\": \"jean@soo.com\",
\"password\": \"|]|{+-\",
\"phone\": \"architecto\",
\"client_id\": 16,
\"is_active\": false,
\"roles\": [
\"Admin\"
]
}"
const url = new URL(
"http://localhost/api/v1/users/1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Jean Dupont",
"email": "jean@soo.com",
"password": "|]|{+-",
"phone": "architecto",
"client_id": 16,
"is_active": false,
"roles": [
"Admin"
]
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"name": "Jean Dupont",
"email": "jean@soo.com",
"is_active": true,
"roles": [
"Admin"
],
"client": null
},
"meta": {
"success": true,
"message": "Utilisateur mis à jour."
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Supprimer un utilisateur.
Example request:
curl --request DELETE \
"http://localhost/api/v1/users/1" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/users/1"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (200):
{
"data": null,
"meta": {
"success": true,
"message": "Utilisateur supprimé."
},
"links": {}
}
Example response (422):
{
"data": null,
"meta": {
"success": false,
"message": "Super Admin role cannot be deleted.",
"code": 422
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Supprimer un utilisateur.
Example request:
curl --request POST \
"http://localhost/api/v1/users/bulk-delete" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost/api/v1/users/bulk-delete"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200):
{
"data": null,
"meta": {
"success": true,
"message": "Utilisateur supprimé."
},
"links": {}
}
Example response (422):
{
"data": null,
"meta": {
"success": false,
"message": "Super Admin role cannot be deleted.",
"code": 422
},
"links": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.