API REST v1
API REST v1
Intégrez Semplio à vos applications, sites e-commerce ou outils internes. L'API REST vous donne un accès programmatique à vos produits, clients, ventes, devis et stock.
https://www.semplio.com/api/v1
JSON (UTF-8)
BUSINESS ou supérieur
Accept: application/json et Content-Type: application/json (pour POST/PUT/PATCH).
Authentification
L'API utilise l'authentification Bearer Token. Les tokens sont créés depuis Paramètres → API dans votre espace Semplio.
Incluez le token dans le header Authorization de chaque requête :
GET /api/v1/products HTTP/1.1
Host: www.semplio.com
Authorization: Bearer sk_live_votre_token_api_ici
Accept: application/json
Démarrage rapide
# Lister vos produits
curl https://www.semplio.com/api/v1/products \
-H "Authorization: Bearer sk_live_VOTRE_TOKEN" \
-H "Accept: application/json"
// PHP avec cURL
$ch = curl_init('https://www.semplio.com/api/v1/products');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer sk_live_VOTRE_TOKEN',
'Accept: application/json',
],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($response['data']);
// JavaScript (fetch)
const response = await fetch('https://www.semplio.com/api/v1/products', {
headers: {
'Authorization': 'Bearer sk_live_VOTRE_TOKEN',
'Accept': 'application/json',
},
});
const { data } = await response.json();
console.log(data);
# Python (requests)
import requests
response = requests.get(
'https://www.semplio.com/api/v1/products',
headers={
'Authorization': 'Bearer sk_live_VOTRE_TOKEN',
'Accept': 'application/json',
}
)
data = response.json()['data']
print(data)
Scopes (Permissions)
Chaque token a des scopes qui définissent les opérations autorisées. Un scope write inclut automatiquement le read correspondant.
| Scope | Accès | Endpoints |
|---|---|---|
products:read | Lire les produits | GET /products, GET /products/{id} |
products:write | Créer, modifier, supprimer des produits + ajuster le stock | POST, PUT, DELETE /products, PATCH /stock |
clients:read | Lire les clients et leurs ventes | GET /clients, GET /clients/{id}/sales |
clients:write | Créer et modifier des clients | POST, PUT /clients |
sales:read | Lire les ventes | GET /sales, GET /sales/{id} |
sales:write | Créer des ventes, ajouter des paiements, annuler | POST /sales, POST /sales/{id}/* |
quotes:read | Lire les devis | GET /quotes, GET /quotes/{id} |
stock:read | Lire les mouvements de stock | GET /stock-movements |
* | Accès complet (tous les scopes) | Tous les endpoints |
Pagination
Toutes les listes sont paginées. Utilisez le paramètre per_page (max 100, défaut 20) et page pour naviguer.
Structure de la réponse
{
"data": [
{ /* objet 1 */ },
{ /* objet 2 */ },
// ...
],
"links": {
"first": "https://www.semplio.com/api/v1/products?page=1",
"last": "https://www.semplio.com/api/v1/products?page=5",
"prev": null,
"next": "https://www.semplio.com/api/v1/products?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 5,
"per_page": 20,
"to": 20,
"total": 94
}
}
Exemple
# Page 2, 50 résultats par page
curl "https://www.semplio.com/api/v1/products?page=2&per_page=50" \
-H "Authorization: Bearer sk_live_..."
meta.total — Nombre total de résultats
meta.last_page — Dernière page
links.next — URL de la page suivante (null si dernière)
Gestion des erreurs
L'API utilise les codes HTTP standards. Toutes les erreurs retournent un JSON avec un champ message.
| Code | Statut | Description |
|---|---|---|
| 200 | OK | Requête réussie |
| 201 | Created | Ressource créée avec succès |
| 401 | Unauthorized | Token manquant, invalide ou expiré |
| 403 | Forbidden | Scope insuffisant pour cette action |
| 404 | Not Found | Ressource introuvable ou n'appartient pas à votre entreprise |
| 422 | Validation Error | Données invalides — voir le champ errors |
| 429 | Too Many Requests | Rate limit dépassé — attendez et réessayez |
| 500 | Server Error | Erreur serveur — contactez le support |
Erreur de validation (422)
{
"message": "The given data was invalid.",
"errors": {
"name": ["Le champ nom est obligatoire."],
"sale_price": ["Le prix de vente doit être supérieur à 0."]
}
}
Scope insuffisant (403)
{
"message": "Scope requis : products:write"
}
Rate Limiting
L'API est limitée à 60 requêtes par minute par token. Chaque réponse inclut des headers de suivi :
X-RateLimit-Limit: 60 ← Quota maximum
X-RateLimit-Remaining: 57 ← Requêtes restantes
Retry-After: 42 ← Secondes avant reset (si 429)
per_page=100) pour réduire le nombre d'appels. Implémentez un backoff exponentiel en cas de 429.
Produits
/api/v1/products
Gérez votre catalogue de produits et services. Trois types disponibles : product (avec stock), product_no_stock (sans stock) et service.
L'objet Produit
{
"id": 42,
"name": "Sac de ciment CIM 50kg",
"description": "Ciment portland CEM II 42.5",
"type": "product",
"barcode": "6001234567890",
"purchase_price": 3800,
"sale_price": 4500,
"quantity": 150,
"alert_quantity": 20,
"is_active": true,
"category": { "id": 3, "name": "Matériaux de construction" },
"unit": { "id": 1, "name": "Sac", "abbreviation": "sac" },
"branch_id": 1,
"created_at": "2026-03-15T10:30:00.000000Z",
"updated_at": "2026-03-20T14:15:00.000000Z"
}
/api/v1/products
products:read
Lister les produits
Retourne une liste paginée de tous les produits de votre entreprise.
Paramètres query
search
|
string | Recherche par nom de produit |
category_id
|
integer | Filtrer par catégorie |
type
|
string | product, product_no_stock ou service |
is_active
|
boolean | Filtrer par statut actif/inactif |
per_page
|
integer | Résultats par page (max 100, défaut 20) |
Requête
curl "https://www.semplio.com/api/v1/products?type=product&per_page=50" \
-H "Authorization: Bearer sk_live_..."
$response = Http::withToken('sk_live_...')
->get('https://www.semplio.com/api/v1/products', [
'type' => 'product',
'per_page' => 50,
]);
$products = $response->json('data');
const res = await fetch(
'https://www.semplio.com/api/v1/products?type=product&per_page=50',
{ headers: { 'Authorization': 'Bearer sk_live_...' } }
);
const { data } = await res.json();
Réponse
200{
"data": [
{
"id": 42,
"name": "Sac de ciment CIM 50kg",
"type": "product",
"sale_price": 4500,
"quantity": 150,
"is_active": true,
"category": { "id": 3, "name": "Matériaux" },
"branch_id": 1,
"created_at": "2026-03-15T10: 30: 00.000000Z"
}
],
"links": { "first": "...?page=1", "next": "...?page=2" },
"meta": { "current_page": 1, "total": 94, "per_page": 50 }
}
/api/v1/products/{id}
products:read
Récupérer un produit
Retourne les détails complets d'un produit avec sa catégorie, son unité et ses fournisseurs.
Aucun paramètre requis.
Requête
curl "https://www.semplio.com/api/v1/products/42" \
-H "Authorization: Bearer sk_live_..."
Réponse
200{
"data": {
"id": 42,
"name": "Sac de ciment CIM 50kg",
"description": "Ciment portland CEM II 42.5",
"type": "product",
"barcode": "6001234567890",
"purchase_price": 3800,
"sale_price": 4500,
"quantity": 150,
"alert_quantity": 20,
"is_active": true,
"category": { "id": 3, "name": "Matériaux de construction" },
"unit": { "id": 1, "name": "Sac", "abbreviation": "sac" },
"suppliers": [
{ "id": 5, "name": "CIM Sénégal", "purchase_price": 3800, "reference": "CIM-50-PT" }
],
"branch_id": 1,
"created_at": "2026-03-15T10: 30: 00.000000Z",
"updated_at": "2026-03-20T14: 15: 00.000000Z"
}
}
/api/v1/products
products:write
Créer un produit
Crée un nouveau produit dans votre catalogue.
Corps de la requête (JSON)
name
|
string requis | Nom du produit (max 255 car.) |
type
|
string requis | product, product_no_stock ou service |
sale_price
|
numeric requis | Prix de vente (≥ 0) |
purchase_price
|
numeric optionnel | Prix d'achat (≥ 0) |
description
|
string optionnel | Description du produit |
quantity
|
numeric optionnel | Stock initial (type product uniquement) |
alert_quantity
|
numeric optionnel | Seuil d'alerte stock |
category_id
|
integer optionnel | ID catégorie existante |
unit_id
|
integer optionnel | ID unité de mesure |
branch_id
|
integer optionnel | ID branche (défaut : branche principale) |
Requête
curl -X POST "https://www.semplio.com/api/v1/products" \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "name": "Riz brisé 25kg", "type": "product",
"sale_price": 12500, "quantity": 200 }'
$response = Http::withToken('sk_live_...')
->post('https://www.semplio.com/api/v1/products', [
'name' => 'Riz brisé 25kg',
'type' => 'product',
'sale_price' => 12500,
'purchase_price' => 10000,
'quantity' => 200,
'alert_quantity' => 30,
'category_id' => 1,
]);
$product = $response->json('data');
const res = await fetch('https://www.semplio.com/api/v1/products', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Riz brisé 25kg',
type: 'product',
sale_price: 12500,
quantity: 200,
}),
});
const { data } = await res.json();
Réponse
201{
"data": {
"id": 85,
"name": "Riz brisé 25kg",
"type": "product",
"sale_price": 12500,
"purchase_price": 10000,
"quantity": 200,
"alert_quantity": 30,
"is_active": true,
"category": { "id": 1, "name": "Alimentation" },
"branch_id": 1,
"created_at": "2026-03-23T09: 00: 00.000000Z",
"updated_at": "2026-03-23T09: 00: 00.000000Z"
}
}
/api/v1/products/{id}
products:write
Modifier un produit
Met à jour un produit existant. Seuls les champs envoyés sont modifiés.
Corps de la requête (JSON)
name
|
string optionnel | Nouveau nom |
sale_price
|
numeric optionnel | Nouveau prix de vente |
purchase_price
|
numeric optionnel | Nouveau prix d'achat |
description
|
string optionnel | Nouvelle description |
is_active
|
boolean optionnel | Activer/désactiver |
Requête
curl -X PUT "https://www.semplio.com/api/v1/products/85" \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "sale_price": 13000, "is_active": true }'
Réponse
200{
"data": {
"id": 85,
"name": "Riz brisé 25kg",
"sale_price": 13000,
"is_active": true,
"updated_at": "2026-03-23T11: 00: 00.000000Z"
}
}
/api/v1/products/{id}
products:write
Supprimer un produit
Supprime un produit (soft delete). Le produit reste en base mais n'apparaît plus dans les listes.
Aucun paramètre requis.
Requête
curl -X DELETE "https://www.semplio.com/api/v1/products/85" \
-H "Authorization: Bearer sk_live_..."
Réponse
200{
"message": "Produit supprimé."
}
/api/v1/products/{id}/stock
products:write
Ajuster le stock
Définit la nouvelle quantité en stock d'un produit. Uniquement pour les produits de type product. Un mouvement de stock est automatiquement créé.
Corps de la requête (JSON)
quantity
|
numeric requis | Nouvelle quantité en stock (≥ 0) |
note
|
string optionnel | Motif de l'ajustement |
Requête
curl -X PATCH "https://www.semplio.com/api/v1/products/42/stock" \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "quantity": 200, "note": "Inventaire physique" }'
Réponse
200{
"message": "Stock ajusté.",
"product_id": 42,
"previous_quantity": 150,
"new_quantity": 200
}
Clients
/api/v1/clients
Gérez votre base de clients. Chaque client est rattaché à une branche de votre entreprise.
L'objet Client
{
"id": 15,
"name": "Awa Diop",
"phone": "+221 77 123 45 67",
"email": "awa.diop@email.com",
"address": "Mermoz, Dakar",
"ninea": null,
"rccm": null,
"loyalty_points": 240,
"balance": 0,
"branch_id": 1,
"created_at": "2026-02-10T08:00:00.000000Z",
"updated_at": "2026-03-20T16:30:00.000000Z"
}
/api/v1/clients
clients:read
Lister les clients
Retourne une liste paginée de vos clients.
Paramètres query
search
|
string | Recherche par nom, téléphone ou email |
per_page
|
integer | Résultats par page (max 100) |
Requête
curl "https://www.semplio.com/api/v1/clients?search=diop" \
-H "Authorization: Bearer sk_live_..."
Réponse
200{
"data": [
{ "id": 15, "name": "Awa Diop", "phone": "+221 77 123 45 67", "email": "awa.diop@email.com", "balance": 0 }
],
"meta": { "current_page": 1, "total": 1 }
}
/api/v1/clients/{id}
clients:read
Récupérer un client
Retourne les détails d'un client.
Aucun paramètre requis.
Requête
curl "https://www.semplio.com/api/v1/clients/15" \
-H "Authorization: Bearer sk_live_..."
Réponse
200{
"data": {
"id": 15,
"name": "Awa Diop",
"phone": "+221 77 123 45 67",
"email": "awa.diop@email.com",
"address": "Mermoz, Dakar",
"loyalty_points": 240,
"balance": 0,
"branch_id": 1
}
}
/api/v1/clients/{id}/sales
clients:read
Ventes d'un client
Retourne l'historique des ventes d'un client avec les articles et paiements.
Aucun paramètre requis.
Requête
curl "https://www.semplio.com/api/v1/clients/15/sales" \
-H "Authorization: Bearer sk_live_..."
Réponse
200{
"data": [
{
"id": 120,
"reference": "VTE-2026-0120",
"status": "completed",
"payment_status": "paid",
"total": 25000,
"paid_amount": 25000,
"remaining_amount": 0,
"items": [
{ "product_name": "Sac de ciment CIM 50kg", "quantity": 5, "unit_price": 4500, "total": 22500 }
],
"created_at": "2026-03-18T10: 00: 00.000000Z"
}
],
"meta": { "total": 12 }
}
/api/v1/clients
clients:write
Créer un client
Crée un nouveau client.
Corps de la requête (JSON)
name
|
string requis | Nom du client (max 255) |
phone
|
string optionnel | Numéro de téléphone |
email
|
email optionnel | Adresse email |
address
|
string optionnel | Adresse postale |
ninea
|
string optionnel | NINEA (entreprises) |
rccm
|
string optionnel | RCCM (entreprises) |
branch_id
|
integer optionnel | ID branche (défaut : principale) |
Requête
curl -X POST "https://www.semplio.com/api/v1/clients" \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "name": "Mamadou Sow",
"phone": "+221 78 900 00 00" }'
$response = Http::withToken('sk_live_...')
->post('https://www.semplio.com/api/v1/clients', [
'name' => 'Mamadou Sow',
'phone' => '+221 78 900 00 00',
'email' => 'm.sow@entreprise.sn',
'address' => 'Plateau, Dakar',
]);
const res = await fetch('https://www.semplio.com/api/v1/clients', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Mamadou Sow',
phone: '+221 78 900 00 00',
}),
});
Réponse
201{
"data": {
"id": 45,
"name": "Mamadou Sow",
"phone": "+221 78 900 00 00",
"email": "m.sow@entreprise.sn",
"address": "Plateau, Dakar",
"loyalty_points": 0,
"balance": 0,
"branch_id": 1,
"created_at": "2026-03-23T09: 30: 00.000000Z"
}
}
/api/v1/clients/{id}
clients:write
Modifier un client
Met à jour un client existant. Seuls les champs envoyés sont modifiés.
Corps de la requête (JSON)
name
|
string optionnel | Nouveau nom |
phone
|
string optionnel | Nouveau téléphone |
email
|
email optionnel | Nouvel email |
address
|
string optionnel | Nouvelle adresse |
Requête
curl -X PUT "https://www.semplio.com/api/v1/clients/45" \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "phone": "+221 78 900 11 11" }'
Réponse
200{
"data": {
"id": 45,
"name": "Mamadou Sow",
"phone": "+221 78 900 11 11",
"updated_at": "2026-03-23T10: 00: 00.000000Z"
}
}
Ventes
/api/v1/sales
Créez et gérez vos ventes. Chaque vente peut contenir plusieurs articles et recevoir des paiements partiels ou complets.
L'objet Vente
{
"id": 120,
"reference": "VTE-2026-0120",
"status": "completed",
"payment_status": "paid",
"subtotal": 26000,
"discount": 500,
"global_discount": 1000,
"tax": 0,
"total": 24500,
"paid_amount": 24500,
"remaining_amount": 0,
"note": null,
"cancel_reason": null,
"cancelled_at": null,
"client": { "id": 15, "name": "Awa Diop" },
"items": [
{
"id": 201,
"product_id": 42,
"product_name": "Sac de ciment CIM 50kg",
"quantity": 5,
"unit_price": 4500,
"discount": 500,
"tax": 0,
"total": 22000
}
],
"payments": [
{ "id": 89, "amount": 24500, "paid_at": "2026-03-18", "payment_mode": "Espèces" }
],
"branch_id": 1,
"user_id": 2,
"created_at": "2026-03-18T10:00:00.000000Z"
}
/api/v1/sales
sales:read
Lister les ventes
Retourne une liste paginée de vos ventes avec les articles et le client.
Paramètres query
status
|
string | pending, completed ou cancelled |
payment_status
|
string | pending, partial, paid ou cancelled |
client_id
|
integer | Filtrer par client |
date_from
|
date | Début période (YYYY-MM-DD) |
date_to
|
date | Fin période (YYYY-MM-DD) |
per_page
|
integer | Résultats par page (max 100) |
Requête
curl "https://www.semplio.com/api/v1/sales?status=completed&date_from=2026-03-01" \
-H "Authorization: Bearer sk_live_..."
Réponse
200{
"data": [
{
"id": 120,
"reference": "VTE-2026-0120",
"status": "completed",
"payment_status": "paid",
"total": 24500,
"paid_amount": 24500,
"client": { "id": 15, "name": "Awa Diop" },
"created_at": "2026-03-18T10: 00: 00.000000Z"
}
],
"meta": { "current_page": 1, "total": 45 }
}
/api/v1/sales/{id}
sales:read
Récupérer une vente
Retourne les détails complets d'une vente avec articles, paiements et client.
Aucun paramètre requis.
Requête
curl "https://www.semplio.com/api/v1/sales/120" \
-H "Authorization: Bearer sk_live_..."
Réponse
200{
"data": {
"id": 120,
"reference": "VTE-2026-0120",
"status": "completed",
"payment_status": "paid",
"subtotal": 26000,
"discount": 500,
"global_discount": 1000,
"tax": 0,
"total": 24500,
"paid_amount": 24500,
"remaining_amount": 0,
"client": { "id": 15, "name": "Awa Diop" },
"items": [
{ "id": 201, "product_id": 42, "product_name": "Sac de ciment CIM 50kg", "quantity": 5, "unit_price": 4500, "discount": 500, "total": 22000 },
{ "id": 202, "product_id": 18, "product_name": "Fer à béton 10mm", "quantity": 10, "unit_price": 400, "discount": 0, "total": 4000 }
],
"payments": [
{ "id": 89, "amount": 15000, "paid_at": "2026-03-18", "payment_mode": "Wave", "reference": "WV-2026-001" },
{ "id": 90, "amount": 9500, "paid_at": "2026-03-18", "payment_mode": "Espèces", "reference": null }
]
}
}
/api/v1/sales
sales:write
Créer une vente
Crée une nouvelle vente avec un ou plusieurs articles. Le stock est automatiquement décrémenté pour les produits de type product.
Corps de la requête (JSON)
client_id
|
integer optionnel | ID client (optionnel pour vente anonyme) |
note
|
string optionnel | Note interne |
global_discount
|
numeric optionnel | Remise globale en FCFA |
items
|
array requis | Liste des articles (min 1) |
items[].product_id
|
integer requis | ID produit |
items[].quantity
|
numeric requis | Quantité (> 0) |
items[].unit_price
|
numeric requis | Prix unitaire (≥ 0) |
items[].discount
|
numeric optionnel | Remise par ligne en FCFA |
Requête
curl -X POST https://www.semplio.com/api/v1/sales \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "client_id": 15, "items": [
{ "product_id": 42, "quantity": 5, "unit_price": 4500 }
] }'
// PHP
$response = Http::withToken('sk_live_...')
->post('https://www.semplio.com/api/v1/sales', [
'client_id' => 15,
'global_discount' => 1000,
'items' => [
['product_id' => 42, 'quantity' => 5, 'unit_price' => 4500],
['product_id' => 18, 'quantity' => 10, 'unit_price' => 400],
],
]);
$sale = $response->json('data');
// JavaScript (fetch)
const res = await fetch('https://www.semplio.com/api/v1/sales', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({
client_id: 15,
global_discount: 1000,
items: [
{ product_id: 42, quantity: 5, unit_price: 4500 },
{ product_id: 18, quantity: 10, unit_price: 400 },
],
}),
});
const { data } = await res.json();
Réponse
201{
"data": {
"id": 121,
"reference": "VTE-2026-0121",
"status": "pending",
"payment_status": "pending",
"subtotal": 26500,
"discount": 500,
"global_discount": 1000,
"total": 25000,
"paid_amount": 0,
"remaining_amount": 25000,
"client": { "id": 15, "name": "Awa Diop" },
"items": [ ...],
"payments": [],
"created_at": "2026-03-23T14: 00: 00.000000Z"
}
}
/api/v1/sales/{id}/payments
sales:write
Ajouter un paiement
Enregistre un paiement sur une vente. Plusieurs paiements possibles (paiement partiel). Le statut de la vente est automatiquement mis à jour.
Corps de la requête (JSON)
amount
|
numeric requis | Montant (> 0) |
payment_mode_id
|
integer requis | ID du mode de paiement |
paid_at
|
date requis | Date effective (YYYY-MM-DD) |
reference
|
string optionnel | Référence du paiement |
note
|
string optionnel | Note |
Requête
curl -X POST "https://www.semplio.com/api/v1/sales/121/payments" \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "amount": 15000, "payment_mode_id": 2,
"paid_at": "2026-03-23" }'
$response = Http::withToken('sk_live_...')
->post('https://www.semplio.com/api/v1/sales/121/payments', [
'amount' => 15000,
'payment_mode_id' => 2,
'paid_at' => '2026-03-23',
'reference' => 'WV-2026-042',
]);
const res = await fetch('https://www.semplio.com/api/v1/sales/121/payments', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: 15000,
payment_mode_id: 2,
paid_at: '2026-03-23',
}),
});
Réponse
201{
"message": "Paiement enregistré.",
"payment_id": 91,
"amount": 15000,
"sale_payment_status": "partial"
}
/api/v1/sales/{id}/cancel
sales:write
Annuler une vente
Annule une vente. Le stock est automatiquement restitué. Un motif est obligatoire.
Corps de la requête (JSON)
reason
|
string requis | Motif d'annulation (3 à 1000 caractères) |
Requête
curl -X POST "https://www.semplio.com/api/v1/sales/121/cancel" \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "reason": "Client a changé de commande" }'
Réponse
200{
"data": {
"id": 121,
"status": "cancelled",
"payment_status": "cancelled",
"cancel_reason": "Client a changé de commande",
"cancelled_at": "2026-03-23T14: 30: 00.000000Z"
}
}
Devis
/api/v1/quotes
Consultez vos devis. Les devis sont en lecture seule via l'API (création et conversion via l'interface web).
/api/v1/quotes
quotes:read
Lister les devis
Retourne une liste paginée de vos devis.
Paramètres query
status
|
string | draft, sent, accepted, rejected, expired ou converted |
client_id
|
integer | Filtrer par client |
per_page
|
integer | Résultats par page (max 100) |
Requête
curl "https://www.semplio.com/api/v1/quotes?status=accepted" \
-H "Authorization: Bearer sk_live_..."
Réponse
200{
"data": [
{
"id": 8,
"reference": "DEV-2026-0008",
"status": "accepted",
"total": 185000,
"valid_until": "2026-04-15",
"client": { "id": 15, "name": "Awa Diop" },
"created_at": "2026-03-10T09: 00: 00.000000Z"
}
],
"meta": { "total": 3 }
}
/api/v1/quotes/{id}
quotes:read
Récupérer un devis
Retourne les détails d'un devis avec articles et client.
Aucun paramètre requis.
Requête
curl "https://www.semplio.com/api/v1/quotes/8" \
-H "Authorization: Bearer sk_live_..."
Réponse
200{
"data": {
"id": 8,
"reference": "DEV-2026-0008",
"status": "accepted",
"valid_until": "2026-04-15",
"subtotal": 190000,
"discount": 5000,
"global_discount": 0,
"tax": 0,
"total": 185000,
"note": "Devis fournitures bureau",
"sale_id": null,
"client": { "id": 15, "name": "Awa Diop", "phone": "+221 77 123 45 67" },
"items": [
{ "id": 20, "product_id": 60, "product_name": "Bureau directeur", "quantity": 2, "unit_price": 75000, "discount": 5000, "total": 145000 },
{ "id": 21, "product_id": 61, "product_name": "Chaise ergonomique", "quantity": 3, "unit_price": 15000, "discount": 0, "total": 45000 }
]
}
}
Mouvements de stock
/api/v1/stock-movements
Consultez l'historique des mouvements de stock. Les mouvements sont générés automatiquement lors des ventes, retours et ajustements.
/api/v1/stock-movements
stock:read
Lister les mouvements
Retourne l'historique paginé des mouvements de stock.
Paramètres query
product_id
|
integer | Filtrer par produit |
type
|
string | in, out, transfer, adjustment ou return |
per_page
|
integer | Résultats par page (max 100) |
Requête
curl "https://www.semplio.com/api/v1/stock-movements?product_id=42&type=out" \
-H "Authorization: Bearer sk_live_..."
Réponse
200{
"data": [
{
"id": 350,
"type": "out",
"product_id": 42,
"product_name": "Sac de ciment CIM 50kg",
"quantity": 5,
"quantity_before": 155,
"quantity_after": 150,
"source_branch_id": 1,
"destination_branch_id": null,
"note": null,
"reference_type": "Sale",
"reference_id": 120,
"user_id": 2,
"created_at": "2026-03-18T10: 00: 00.000000Z"
}
],
"meta": { "total": 23 }
}
Semplio Score
/api/v1/score
Score de santé financière de votre entreprise (0-100), calculé automatiquement à partir de 8 métriques pondérées. Partageable avec les banques et partenaires.
/api/v1/score
Récupérer le score
Retourne le Semplio Score actuel avec le breakdown par métrique.
Aucun paramètre requis.
Requête
curl "https://www.semplio.com/api/v1/score" \
-H "Authorization: Bearer sk_live_..."
Réponse
200{
"data": {
"score": 72,
"level": "bon",
"breakdown": {
"revenue_regularity": 85,
"gross_margin": 71,
"cash_ratio": 60,
"collection_rate": 90,
"client_diversification": 45,
"stock_health": 100,
"activity_tenure": 50,
"accounting_compliance": 100
},
"calculated_at": "2026-03-23T05: 00: 00.000000Z"
}
}
Webhooks
/api/v1/webhooks
Recevez des notifications en temps réel lorsque des événements se produisent dans votre espace Semplio.
Événements disponibles
sale.created
Vente créée
sale.completed
Vente terminée
sale.cancelled
Vente annulée
payment.received
Paiement reçu
client.created
Client créé
quote.created
Devis créé
quote.converted
Devis converti en vente
expense.created
Dépense créée
product.stock_alert
Alerte stock bas
subscription.renewed
Abonnement renouvelé
Vérification de signature
Chaque webhook envoyé inclut un header X-Webhook-Signature contenant un HMAC-SHA256 du body signé avec votre secret.
// Vérifier la signature du webhook
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'];
$expected = hash_hmac('sha256', $payload, $votre_secret);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit('Signature invalide');
}
$event = json_decode($payload, true);
// Traiter l'événement...
// Node.js — Express middleware
const crypto = require('crypto');
app.post('/webhook', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const expected = crypto
.createHmac('sha256', VOTRE_SECRET)
.update(JSON.stringify(req.body))
.digest('hex');
if (signature !== expected) return res.status(401).send('Invalid');
// Traiter l'événement...
res.sendStatus(200);
});
# Python — Flask
import hmac, hashlib
@app.route('/webhook', methods=['POST'])
def handle_webhook():
signature = request.headers.get('X-Webhook-Signature')
expected = hmac.new(
VOTRE_SECRET.encode(),
request.data,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, expected):
return 'Invalid', 401
# Traiter l'événement...
return '', 200
Exemple de payload
{
"event": "sale.created",
"timestamp": "2026-03-23T14:00:00.000000Z",
"data": {
"id": 121,
"reference": "VTE-2026-0121",
"status": "pending",
"total": 25000,
"client": { "id": 15, "name": "Awa Diop" }
}
}
Retry : Si votre endpoint ne retourne pas un code 2xx, Semplio réessaie 3 fois (immédiat, +1h, +24h).
Timeout : Votre endpoint doit répondre en moins de 10 secondes.
Conseil : Répondez 200 immédiatement et traitez l'événement de manière asynchrone.
Gestion des webhooks
/api/v1/webhooks
Lister les webhooks
Retourne la liste de vos webhooks configurés.
Aucun paramètre requis.
Requête
curl "https://www.semplio.com/api/v1/webhooks" \
-H "Authorization: Bearer sk_live_..."
Réponse
200{
"data": [
{
"id": 1,
"url": "https://votre-app.com/webhooks/semplio",
"events": ["sale.created", "payment.received"],
"is_active": true,
"last_called_at": "2026-03-22T18: 30: 00.000000Z",
"failure_count": 0,
"created_at": "2026-03-01T10: 00: 00.000000Z"
}
]
}
/api/v1/webhooks
Créer un webhook
Crée un nouveau webhook. Le secret est retourné une seule fois dans la réponse de création.
Corps de la requête (JSON)
url
|
url requis | URL de callback (HTTPS recommandé) |
events
|
array requis | Liste des événements à écouter |
Requête
curl -X POST "https://www.semplio.com/api/v1/webhooks" \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://votre-app.com/webhooks/semplio",
"events": ["sale.created", "payment.received", "client.created"]
}'
Réponse
201{
"data": {
"id": 2,
"url": "https://votre-app.com/webhooks/semplio",
"events": ["sale.created", "payment.received", "client.created"],
"is_active": true,
"secret": "whsec_a1b2c3d4e5f6g7h8i9j0..."
},
"message": "Webhook créé. Conservez le secret, il ne sera plus affiché."
}
/api/v1/webhooks/{id}
Supprimer un webhook
Supprime un webhook. Les événements ne seront plus envoyés à cette URL.
Aucun paramètre requis.
Requête
curl -X DELETE "https://www.semplio.com/api/v1/webhooks/2" \
-H "Authorization: Bearer sk_live_..."
Réponse
200{
"message": "Webhook supprimé."
}
Besoin d'aide pour intégrer l'API ?
Notre équipe technique peut vous accompagner dans l'intégration.
Contactez-nous