MENU navbar-image

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 :

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

Email 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": {}
}
 

Request      

POST api/v1/auth/login

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Body Parameters

email   string     

Email de l'utilisateur. Example: admin@soo.com

password   string     

Mot de passe. Example: password

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":{}}
 

Request      

GET api/v1/auth/me

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

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": {}
}
 

Request      

POST api/v1/auth/refresh

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

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": {}
}
 

Request      

POST api/v1/auth/logout

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

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": {}
}
 

Request      

PUT api/v1/auth/password

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Body Parameters

current_password   string     

Mot de passe actuel. Example: password

password   string     

Nouveau mot de passe (min 8). Example: newpassword

password_confirmation   string     

Confirmation. Example: newpassword

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": {}
}
 

Request      

POST api/v1/auth/tokens

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Body Parameters

name   string     

Nom du token. Example: Integration ERP

abilities   string[]  optional    

Capacités du token (par défaut: ["*"]).

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": {}
}
 

Request      

GET api/v1/auth/tokens

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

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": {}
}
 

Request      

DELETE api/v1/auth/tokens/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

ID du token. Example: 1

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
    }
}
 

Request      

GET api/v1/clients

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

search   string  optional    

Recherche sur nom/code/email. Example: DEMO

is_active   boolean  optional    

Filtrer par statut. Example: true

per_page   integer  optional    

Items par page (défaut 15). Example: 20

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": {}
}
 

Request      

POST api/v1/clients

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Body Parameters

name   string     

Example: ACME Logistique

code   string     

unique Example: ACME-001

email   string  optional    

nullable Example: contact@acme.com

phone   string  optional    

nullable Example: +225 00 00 00 00

address   string  optional    

nullable Example: Abidjan

is_active   boolean  optional    

Default: true Example: false

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": {}
}
 

Request      

GET api/v1/clients/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the client. Example: 1

client   integer     

Example: 1

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": {}
}
 

Request      

PUT api/v1/clients/{id}

PATCH api/v1/clients/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the client. Example: 1

client   integer     

Example: 1

Body Parameters

name   string  optional    

Example: architecto

code   string  optional    

unique Example: architecto

email   string  optional    

Example: gbailey@example.net

phone   string  optional    

Example: architecto

address   string  optional    

Example: architecto

is_active   boolean  optional    

Example: false

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": {}
}
 

Request      

DELETE api/v1/clients/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the client. Example: 1

client   integer     

Example: 2

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": {}
}
 

Request      

POST api/v1/clients/{client_id}/toggle-active

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

client_id   integer     

The ID of the client. Example: 1

client   integer     

Example: 1

Body Parameters

is_active   boolean     

Example: false

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
    }
}
 

Request      

GET api/v1/documents

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

type   string  optional    

Filtrer par type (customs, shipping, invoice, contract, other). Example: invoice

documentable_type   string  optional    

Filtrer par type d'entité. Example: Modules\UserManagement\Models\Client

documentable_id   integer  optional    

Filtrer par ID d'entité. Example: 1

search   string  optional    

Recherche sur le nom. Example: BL

per_page   integer  optional    

Items par page (défaut 15). Example: 20

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": {}
}
 

Request      

POST api/v1/documents

Headers

Content-Type        

Example: multipart/form-data

Accept        

Example: application/json

Body Parameters

file   file     

Fichier (max 20MB). Example: /tmp/phpjkgn6vbjlmh72k2ThPB

type   string  optional    

Type de document. Example: shipping

description   string  optional    

nullable Example: Eius et animi quos velit et.

documentable_type   string  optional    

nullable Example: Modules\UserManagement\Models\Client

documentable_id   integer  optional    

nullable Example: 1

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": {}
}
 

Request      

GET api/v1/documents/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the document. Example: 16

document   integer     

Example: 1

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": {}
}
 

Request      

PUT api/v1/documents/{id}

PATCH api/v1/documents/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the document. Example: 16

document   integer     

Example: 1

Body Parameters

name   string  optional    

Example: architecto

type   string  optional    

Example: architecto

description   string  optional    

Example: Eius et animi quos velit et.

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": {}
}
 

Request      

DELETE api/v1/documents/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the document. Example: 16

document   integer     

Example: 1

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
 

Request      

GET api/v1/documents/{document_id}/download

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

document_id   integer     

The ID of the document. Example: 16

document   integer     

Example: 1

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
    }
}
 

Request      

GET api/v1/dossiers-douane

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

status   string  optional    

Filtrer par statut. Example: approved

type   string  optional    

Filtrer par type (import, export, transit). Example: import

client_id   integer  optional    

Filtrer par client. Example: 1

search   string  optional    

Recherche sur référence/description. Example: DD-2026

per_page   integer  optional    

Items par page (défaut 15). Example: 20

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": {}
}
 

Request      

POST api/v1/dossiers-douane

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Body Parameters

type   string  optional    

Type: import, export, transit. Example: import

client_id   integer  optional    

nullable Example: 1

origin_country   string  optional    

nullable Example: Côte d'Ivoire

destination_country   string  optional    

nullable Example: France

goods_description   string  optional    

nullable Example: Conteneurs de café

goods_value   number  optional    

nullable Example: 5000000

currency   string  optional    

Default: XAF Example: XAF

weight_kg   number  optional    

nullable Example: 12000

containers   string[]  optional    

nullable

notes   string  optional    

nullable Example: architecto

metadata   object  optional    

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": {}
}
 

Request      

GET api/v1/dossiers-douane/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the dossiers douane. Example: 1

dossier   integer     

Example: 1

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": {}
}
 

Request      

PUT api/v1/dossiers-douane/{id}

PATCH api/v1/dossiers-douane/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the dossiers douane. Example: 1

dossier   integer     

Example: 1

Body Parameters

type   string  optional    
client_id   integer  optional    

Must match an existing stored value. Example: 16

origin_country   string  optional    

Must not be greater than 100 characters. Example: n

destination_country   string  optional    

Must not be greater than 100 characters. Example: g

goods_description   string  optional    

Must not be greater than 2000 characters. Example: z

goods_value   number  optional    

Must be at least 0. Example: 77

currency   string  optional    

Must be 3 characters. Example: iyv

weight_kg   number  optional    

Must be at least 0. Example: 42

containers   string[]  optional    

Must not be greater than 50 characters.

notes   string  optional    

Must not be greater than 2000 characters. Example: j

metadata   object  optional    

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": {}
}
 

Request      

DELETE api/v1/dossiers-douane/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the dossiers douane. Example: 1

dossier   integer     

Example: 1

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": {}
}
 

Request      

POST api/v1/dossiers-douane/{dossier_id}/status

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

dossier_id   integer     

The ID of the dossier. Example: 1

dossier   integer     

Example: 1

Body Parameters

status   string     

Nouveau statut (draft, submitted, in_review, approved, rejected, cleared). Example: submitted

notes   string  optional    

nullable Notes sur le changement de statut. Example: architecto

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": {}
}
 

Request      

GET api/v1

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

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": {}
}
 

Request      

GET api/v1/tracking/{reference}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

reference   string     

Example: architecto

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
    }
}
 

Request      

GET api/v1/expeditions

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

status   string  optional    

Example: in_transit

type   string  optional    

Example: sea

client_id   integer  optional    

Example: 1

search   string  optional    

Recherche sur référence/tracking/BL. Example: EXP-2026

per_page   integer  optional    

Example: 20

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": {}
}
 

Request      

POST api/v1/expeditions

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Body Parameters

type   string  optional    

Example: sea

client_id   integer  optional    

nullable Example: 1

origin   string  optional    

nullable Example: Abidjan

destination   string  optional    

nullable Example: Le Havre

carrier   string  optional    

nullable Example: Maersk

tracking_number   string  optional    

nullable Example: MAEU123456

container_number   string  optional    

nullable Example: MSCU1234567

bill_of_lading   string  optional    

nullable Example: BL-2026-001

estimated_departure   datetime  optional    

nullable Example: 2026-08-01T08:00:00Z

estimated_arrival   datetime  optional    

nullable Example: 2026-08-20T08:00:00Z

notes   string  optional    

nullable Example: architecto

metadata   object  optional    

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": {}
}
 

Request      

GET api/v1/expeditions/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the expedition. Example: 1

expedition   integer     

Example: 1

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": {}
}
 

Request      

PUT api/v1/expeditions/{id}

PATCH api/v1/expeditions/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the expedition. Example: 1

expedition   integer     

Example: 1

Body Parameters

type   string  optional    
client_id   integer  optional    

Must match an existing stored value. Example: 16

origin   string  optional    

Must not be greater than 200 characters. Example: n

destination   string  optional    

Must not be greater than 200 characters. Example: g

carrier   string  optional    

Must not be greater than 200 characters. Example: z

tracking_number   string  optional    

Must not be greater than 100 characters. Example: m

container_number   string  optional    

Must not be greater than 50 characters. Example: i

bill_of_lading   string  optional    

Must not be greater than 100 characters. Example: y

estimated_departure   string  optional    

Must be a valid date. Example: 2026-07-06T21:38:49

actual_departure   string  optional    

Must be a valid date. Example: 2026-07-06T21:38:49

estimated_arrival   string  optional    

Must be a valid date. Example: 2026-07-06T21:38:49

actual_arrival   string  optional    

Must be a valid date. Example: 2026-07-06T21:38:49

notes   string  optional    

Must not be greater than 2000 characters. Example: v

metadata   object  optional    

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": {}
}
 

Request      

DELETE api/v1/expeditions/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the expedition. Example: 1

expedition   integer     

Example: 1

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": {}
}
 

Request      

POST api/v1/expeditions/{expedition_id}/status

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

expedition_id   integer     

The ID of the expedition. Example: 1

expedition   integer     

Example: 1

Body Parameters

status   string     

Example: in_transit

location   string  optional    

nullable Example: Port d'Abidjan

description   string  optional    

nullable Example: Conteneur chargé sur le navire

occurred_at   datetime  optional    

nullable Example: 2026-08-01T10:00:00Z

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
    }
}
 

Request      

GET api/v1/factures

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

status   string  optional    

Example: sent

client_id   integer  optional    

Example: 1

search   string  optional    

Recherche sur référence/notes. Example: FAC-2026

per_page   integer  optional    

Example: 20

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": {}
}
 

Request      

POST api/v1/factures

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Body Parameters

client_id   integer  optional    

nullable Example: 1

expedition_id   integer  optional    

nullable Example: 1

dossier_douane_id   integer  optional    

nullable Example: 1

issue_date   date     

Example: 2026-07-06

due_date   date  optional    

nullable Example: 2026-08-06

subtotal   number     

Example: 5000000

tax_rate   number  optional    

nullable Example: 18

discount   number  optional    

nullable Example: 0

currency   string  optional    

Default: XAF Example: XAF

items   string[]  optional    

nullable Lignes de facturation

description   string  optional    

This field is required when items is present. Example: Eius et animi quos velit et.

quantity   number  optional    

This field is required when items is present. Must be at least 0. Example: 60

unit_price   number  optional    

This field is required when items is present. Must be at least 0. Example: 42

notes   string  optional    

nullable Example: architecto

metadata   object  optional    

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": {}
}
 

Request      

GET api/v1/factures/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the facture. Example: 1

facture   integer     

Example: 1

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": {}
}
 

Request      

PUT api/v1/factures/{id}

PATCH api/v1/factures/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the facture. Example: 1

facture   integer     

Example: 1

Body Parameters

client_id   integer  optional    

Must match an existing stored value. Example: 16

expedition_id   integer  optional    

Example: 16

dossier_douane_id   integer  optional    

Example: 16

issue_date   string  optional    

Must be a valid date. Example: 2026-07-06T21:38:49

due_date   string  optional    

Must be a valid date. Must be a date after or equal to issue_date. Example: 2052-07-29

subtotal   number  optional    

Must be at least 0. Example: 39

tax_rate   number  optional    

Must be at least 0. Must not be greater than 100. Example: 7

discount   number  optional    

Must be at least 0. Example: 12

currency   string  optional    

Must be 3 characters. Example: miy

items   object[]  optional    
description   string  optional    

This field is required when items is present. Example: Eius et animi quos velit et.

quantity   number  optional    

This field is required when items is present. Must be at least 0. Example: 60

unit_price   number  optional    

This field is required when items is present. Must be at least 0. Example: 42

notes   string  optional    

Must not be greater than 2000 characters. Example: v

metadata   object  optional    

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": {}
}
 

Request      

DELETE api/v1/factures/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the facture. Example: 1

facture   integer     

Example: 1

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": {}
}
 

Request      

POST api/v1/factures/{facture_id}/validate

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

facture_id   integer     

The ID of the facture. Example: 1

facture   integer     

Example: 1

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": {}
}
 

Request      

POST api/v1/factures/{facture_id}/send

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

facture_id   integer     

The ID of the facture. Example: 1

facture   integer     

Example: 1

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": {}
}
 

Request      

POST api/v1/factures/{facture_id}/payments

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

facture_id   integer     

The ID of the facture. Example: 1

facture   integer     

Example: 1

Body Parameters

amount   number     

Example: 3000000

method   string  optional    

nullable Example: bank_transfer

reference   string  optional    

nullable Example: VIREMENT-001

paid_at   date     

Example: 2026-07-10

notes   string  optional    

nullable Example: architecto

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": {}
}
 

Request      

POST api/v1/factures/{facture_id}/cancel

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

facture_id   integer     

The ID of the facture. Example: 1

facture   integer     

Example: 1

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
    }
}
 

Request      

GET api/v1/imports-exports

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

type   string  optional    

Filtrer par type (import, export). Example: export

module   string  optional    

Filtrer par module. Example: douane

status   string  optional    

Filtrer par statut. Example: completed

per_page   integer  optional    

Example: 15

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": {}
}
 

Request      

GET api/v1/imports-exports/{record_id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

record_id   integer     

The ID of the record. Example: 16

record   integer     

Example: 1

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": {}
}
 

Request      

POST api/v1/exports

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Body Parameters

module   string     

Module à exporter (douane, expedition, facturation). Example: douane

format   string  optional    

Format de sortie (xlsx, csv). Default: xlsx. Example: xlsx

filters   object  optional    

nullable Filtres à appliquer (status, type, client_id).

status   string  optional    

Example: architecto

type   string  optional    

Example: architecto

client_id   integer  optional    

Example: 16

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": {}
}
 

Request      

POST api/v1/imports

Headers

Content-Type        

Example: multipart/form-data

Accept        

Example: application/json

Body Parameters

module   string     

Module à importer (douane, expedition, facturation). Example: douane

file   file     

Fichier Excel/CSV à importer (max 10MB). Example: /tmp/phpnoeg9uajgpvm4x5YvgF

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": {}
}
 

Request      

GET api/v1/imports-exports/{record_id}/download

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

record_id   integer     

The ID of the record. Example: 16

record   integer     

Example: 1

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": {}
}
 

Request      

POST api/v1/imports-exports/{record_id}/cancel

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

record_id   integer     

The ID of the record. Example: 16

record   integer     

Example: 1

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
 

Request      

GET api/v1/import-templates/{module}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

module   string     

Example: architecto

Query Parameters

module   string     

Example: douane

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
    }
}
 

Request      

GET api/v1/notifications

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

type   string  optional    

Filtrer par type. Example: facture.created

unread   boolean  optional    

Si 1, uniquement les non lues. Example: true

per_page   integer  optional    

Items par page (défaut 15). Example: 20

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": {}
}
 

Request      

GET api/v1/notifications/unread-count

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

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": {}
}
 

Request      

PATCH api/v1/notifications/{id}/read

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the notification. Example: architecto

notification   integer     

Example: 1

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": {}
}
 

Request      

PATCH api/v1/notifications/read-all

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

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": {}
}
 

Request      

DELETE api/v1/notifications/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the notification. Example: architecto

notification   integer     

Example: 1

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
    }
}
 

Request      

GET api/v1/users

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

search   string  optional    

Recherche sur nom/email. Example: admin

role   string  optional    

Filtrer par rôle. Example: Opérateur

client_id   integer  optional    

Filtrer par client. Example: 1

per_page   integer  optional    

Items par page (défaut 15). Example: 20

page   integer  optional    

Numéro de page. Example: 1

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": {}
}
 

Request      

POST api/v1/users

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Body Parameters

name   string     

Example: Jean Dupont

email   string     

Example: jean@soo.com

password   string     

min:8 Example: password

phone   string  optional    

Example: +225 00 00 00 00

client_id   integer  optional    

nullable Example: 1

is_active   boolean  optional    

Default: true Example: true

roles   string[]     

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": {}
}
 

Request      

GET api/v1/users/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the user. Example: 1

user   integer     

Example: 1

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": {}
}
 

Request      

PUT api/v1/users/{id}

PATCH api/v1/users/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the user. Example: 1

user   integer     

Example: 1

Body Parameters

name   string  optional    

Example: Jean Dupont

email   string  optional    

Example: jean@soo.com

password   string  optional    

min:8 nullable Example: |]|{+-

phone   string  optional    

nullable Example: architecto

client_id   integer  optional    

nullable Example: 16

is_active   boolean  optional    

Example: false

roles   string[]  optional    

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": {}
}
 

Request      

DELETE api/v1/users/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ID of the user. Example: 1

user   integer     

Example: 13

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": {}
}
 

Request      

POST api/v1/users/bulk-delete

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

user   integer     

Example: 13