← Documentation

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.

Base URL
https://www.semplio.com/api/v1
Format

JSON (UTF-8)

Plan requis

BUSINESS ou supérieur

Toutes les requêtes doivent inclure les headers 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 :

Requête HTTP
GET /api/v1/products HTTP/1.1
Host: www.semplio.com
Authorization: Bearer sk_live_votre_token_api_ici
Accept: application/json
Important : Le token n'est affiché qu'une seule fois à la création. Conservez-le en lieu sûr. En cas de perte, révoquez-le et créez-en un nouveau.

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:readLire les produitsGET /products, GET /products/{id}
products:writeCréer, modifier, supprimer des produits + ajuster le stockPOST, PUT, DELETE /products, PATCH /stock
clients:readLire les clients et leurs ventesGET /clients, GET /clients/{id}/sales
clients:writeCréer et modifier des clientsPOST, PUT /clients
sales:readLire les ventesGET /sales, GET /sales/{id}
sales:writeCréer des ventes, ajouter des paiements, annulerPOST /sales, POST /sales/{id}/*
quotes:readLire les devisGET /quotes, GET /quotes/{id}
stock:readLire les mouvements de stockGET /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
200OKRequête réussie
201CreatedRessource créée avec succès
401UnauthorizedToken manquant, invalide ou expiré
403ForbiddenScope insuffisant pour cette action
404Not FoundRessource introuvable ou n'appartient pas à votre entreprise
422Validation ErrorDonnées invalides — voir le champ errors
429Too Many RequestsRate limit dépassé — attendez et réessayez
500Server ErrorErreur 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)
Bonnes pratiques : Mettez en cache les résultats fréquemment consultés. Utilisez la pagination avec des pages plus grandes (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"
}
GET /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 }
}
GET /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"
  }
}
POST /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"
  }
}
PUT /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"
  }
}
DELETE /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é."
}
PATCH /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"
}
GET /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 }
}
GET /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
  }
}
GET /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 }
}
POST /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"
  }
}
PUT /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"
}
GET /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 }
}
GET /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 }
    ]
  }
}
POST /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"
  }
}
POST /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"
}
POST /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).

GET /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 }
}
GET /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.

GET /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.

GET /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"
  }
}
POST /api/v1/score/share

Générer un lien de partage

Génère un lien public sécurisé à durée limitée pour partager votre score avec un tiers (banque, partenaire).

Corps de la requête (JSON)
days integer optionnel Durée de validité en jours (max 90, défaut 30)
Requête
curl -X POST "https://www.semplio.com/api/v1/score/share" \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "days": 30 }'
Réponse
200
{
  "share_url": "https://www.semplio.com/score/abc123def456...",
  "expires_at": "2026-04-22T19: 55: 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

GET /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"
    }
  ]
}
POST /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é."
}
DELETE /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