Branchez votre site, votre boutique en ligne ou votre logiciel métier sur Almawarid : catalogue et stock en temps réel, factures, clients, et des webhooks qui vous préviennent au lieu de vous faire interroger.
https://almawarid.app/api/
429 : espacez vos appels, ne les relancez pas en boucle.
403 avec "mode": "lecture_seule".
limit (200 au plus, 100 par défaut) et offset ; le nombre total d'éléments est rendu dans l'en-tête X-Total-Count.
# Lire le catalogue avec les quantités en stock curl -s https://almawarid.app/api/stock/products/?active=1 \ -H "Authorization: Token VOTRE_JETON" # Poser une entrée de stock (mode lecture/écriture requis) curl -s -X POST https://almawarid.app/api/stock/move/ \ -H "Authorization: Token VOTRE_JETON" \ -H "Content-Type: application/json" \ -d '{"product_id": 12, "delta": 10, "reason": "Réception fournisseur"}'
# pip install requests import requests BASE = "https://almawarid.app/api" ENTETES = {"Authorization": "Token VOTRE_JETON"} # 1) Lire le catalogue et les quantités r = requests.get(f"{BASE}/stock/products/", headers=ENTETES, params={"active": 1}, timeout=20) r.raise_for_status() for produit in r.json(): print(produit["sku"], produit["name"], produit["quantity"]) # 2) Entrée de stock — nécessite le mode lecture/écriture r = requests.post(f"{BASE}/stock/move/", headers=ENTETES, timeout=20, json={"product_id": 12, "delta": 10, "reason": "Réception fournisseur"}) if r.status_code == 403 and r.json().get("mode") == "lecture_seule": print("Clé en lecture seule : demandez le mode écriture.") elif r.status_code == 429: print("Plafond atteint (20 appels/minute) : ralentissez.") else: print(r.json()) # {"movement_id": 901, "quantity": 33.0}
<?php $base = 'https://almawarid.app/api'; $entetes = ['Authorization: Token VOTRE_JETON', 'Content-Type: application/json']; function appel($url, $entetes, $corps = null) { $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => $entetes, CURLOPT_TIMEOUT => 20, ]); if ($corps !== null) { curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($corps)); } $reponse = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); return [$code, json_decode($reponse, true)]; } // 1) Catalogue + stock list($code, $produits) = appel("$base/stock/products/?active=1", $entetes); foreach ($produits as $p) { echo $p['sku'], ' ', $p['name'], ' ', $p['quantity'], PHP_EOL; } // 2) Entrée de stock (mode lecture/écriture requis) list($code, $res) = appel("$base/stock/move/", $entetes, ['product_id' => 12, 'delta' => 10, 'reason' => 'Réception fournisseur']); if ($code === 403 && ($res['mode'] ?? '') === 'lecture_seule') { echo "Clé en lecture seule : demandez le mode écriture.", PHP_EOL; } elseif ($code === 429) { echo "Plafond atteint : 20 appels par minute.", PHP_EOL; }
| Code | Sens | Que faire |
|---|---|---|
200 / 201 | Success | La réponse est du JSON. |
400 | Saisie illisible | Le message précise le champ, et l'index de la ligne fautive le cas échéant. Rien n'a été enregistré. |
401 | Jeton absent ou invalide | Vérifiez l'en-tête Authorization. |
402 | Module API non activé | Demandez l'activation du module. |
402 | Abonnement expiré : écriture suspendue | Le corps porte paywall=true et le motif. Les lectures restent permises : vos données sont toujours récupérables. |
403 | Droit insuffisant, ou clé en lecture seule | Le corps précise mode=lecture_seule le cas échéant. |
404 | Introuvable | L'objet n'existe pas, ou appartient à une autre société. |
409 | Conflit | L'opération est déjà faite (validation, sortie de stock) ou interdite par l'état du document. |
429 | Plafond dépassé | Attendez : 20 appels par minute maximum. |
L'accès programmatique n'est inclus dans aucun abonnement : il s'active à la demande sur n'importe quel plan, sans réinstallation.
L'usage normal du logiciel — application mobile, poste de bureau, pointeuses biométriques — ne nécessite pas ce module.
Documentation Activer le module API/api/billing/invoices/
Factures de la société (100 au plus). Un employé sans le droit « voit toutes les factures » ne voit que les siennes.
[{"id":41,"number":"FAC-2026-0041","invoice_type":"facture","client_id":7,"status":"sent","total_ht":"10000.00","total_ttc":"11900.00"}]
/api/billing/invoices/create/
✏️ mode écriture requis
Crée une facture brouillon (numéro provisoire ; le numéro définitif est tiré à l'émission). Quota de pièces du plan appliqué.
{"client_id":7,"date":"2026-10-08","payment_method":"virement","lines":[{"description":"Prestation","qty":1,"unit_price":"10000","tax_rate":19}]}
{"id":42,"number":"BRO-FAC-0007","status":"draft","total_ttc":"11900.00","lines":[…]}
/api/billing/invoices/<invoice_id>/
Une facture avec ses lignes.
{"id":42,"number":"FAC-2026-0042","lines":[{"description":"Prestation","qty":"1.00","unit_price":"10000.00"}]}
/api/billing/invoices/<invoice_id>/status/
✏️ mode écriture requis
Change le statut. Mêmes verrous que l'écran : une facture numérotée ne redevient pas brouillon, une facture encaissée ne s'annule pas (avoir), « payée » exige un reste dû nul — sinon 409.
{"status":"sent"}
{"id":42,"status":"sent"}
/api/billing/invoices/<invoice_id>/payments/
Versements enregistrés sur un document.
[{"id":9,"invoice_id":42,"amount":"5000.00","date":"2026-10-08","method":"virement","reference_number":"VIR-1"}]
/api/billing/invoices/<invoice_id>/payments/
✏️ mode écriture requis
Enregistre un versement. Un brouillon encaissé est validé automatiquement (numéro définitif) ; le statut « payée » se pose seul quand les versements couvrent le total, timbre compris. Document annulé ou proforma déjà facturée : 409.
{"amount":"5000","method":"virement","reference_number":"VIR-1"}
{"payment":{"id":9,"amount":"5000.00"},"invoice":{"id":42,"number":"FAC-2026-0042","status":"confirmed","balance_remaining":"6900.00"},"excedent":"0"}
/api/billing/invoices/<invoice_id>/pdf/
Le document imprimable (HTML prêt à imprimer, identique au bouton « PDF » de l'écran ; « Enregistrer au format PDF » depuis le navigateur). Fonctionne pour tout type de pièce.
text/html — FAC-2026-0042.html
/api/billing/quotes/
Devis (liste paginée).
[{"id":51,"number":"DEV-2026-0012","invoice_type":"devis","status":"draft","total_ttc":"3571.19"}]
/api/billing/quotes/create/
✏️ mode écriture requis
Crée un devis. Même corps pour proformas, bons de commande, bons de livraison et avoirs.
{"client_id":7,"date":"2026-10-08","lines":[{"description":"Ciment 50 kg","qty":"2","unit_price":"1500,50","tax_rate":19}]}
{"id":51,"number":"DEV-2026-0012","total_ht":"3001.00","total_ttc":"3571.19","lines":[…]}
/api/billing/quotes/<doc_id>/
Un devis avec ses lignes et versements.
{"id":51,"lines":[…],"payments":[]}
/api/billing/proformas/
Proformas (liste paginée).
[{"id":60,"number":"PRO-2026-0004"}]
/api/billing/proformas/create/
✏️ mode écriture requis
Crée une proforma (corps identique aux devis).
{"client_id":7,"lines":[{"description":"Lot A","qty":1,"unit_price":"250000"}]}
{"id":60,"number":"PRO-2026-0004"}
/api/billing/proformas/<doc_id>/
Une proforma.
{"id":60,"lines":[…]}
/api/billing/proformas/<doc_id>/invoice/
✏️ mode écriture requis
Facture la proforma par la même fonction que l'écran : lignes, échéancier et versements suivent. Déjà facturée : rend sa facture (200, creee=false).
{}
{"id":61,"number":"BRO-FAC-0008","invoice_type":"facture","source_document_id":60,"creee":true}
/api/billing/orders/
Bons de commande client (liste paginée).
[{"id":70,"number":"BC-2026-0003"}]
/api/billing/orders/create/
✏️ mode écriture requis
Crée un bon de commande client (TVA par défaut 0, comme l'écran ; exchange_rate pour une devise étrangère).
{"client_id":7,"currency":"DZD","lines":[{"description":"Palette","qty":3,"unit_price":"9000"}]}
{"id":70,"number":"BC-2026-0003"}
/api/billing/orders/<doc_id>/
Un bon de commande.
{"id":70,"lines":[…]}
/api/billing/delivery-notes/
Bons de livraison (liste paginée).
[{"id":80,"number":"BL-2026-0021"}]
/api/billing/delivery-notes/create/
✏️ mode écriture requis
Crée un bon de livraison (TVA par défaut 0). Le stock ne bouge pas à la création : voir stock-out.
{"client_id":7,"lines":[{"description":"Ciment 50 kg","qty":2,"unit_price":"1500"}]}
{"id":80,"number":"BL-2026-0021"}
/api/billing/delivery-notes/<doc_id>/
Un bon de livraison.
{"id":80,"lines":[…]}
/api/billing/delivery-notes/<doc_id>/stock-out/
✏️ mode écriture requis
Sort la marchandise du stock, UNE fois (rejouée : 409). Lignes rapprochées des produits par leur nom, nomenclatures consommées, comme l'écran.
{"depot_id":2}
{"bl_id":80,"produits_sortis":1,"lignes_sans_produit":[],"depot_id":2}
/api/billing/credit-notes/
Avoirs (liste paginée).
[{"id":90,"number":"AVO-2026-0002"}]
/api/billing/credit-notes/create/
✏️ mode écriture requis
Crée un avoir brouillon (pièce fiscale : numéro définitif à l'émission). Indiquez la facture d'origine dans reference.
{"client_id":7,"reference":"Annule FAC-2026-0041","lines":[{"description":"Retour","qty":1,"unit_price":"1000"}]}
{"id":90,"number":"BRO-AVO-0001","invoice_type":"avoir"}
/api/billing/credit-notes/<doc_id>/
Un avoir.
{"id":90,"lines":[…]}
/api/billing/clients/
Clients de la société.
[{"id":7,"name":"SARL Atlas","city":"Oran","phone":"0550123456","nif":"000016001234567"}]
/api/billing/clients/create/
✏️ mode écriture requis
Crée un client (déclenche le webhook client.created).
{"name":"SARL Atlas","city":"Oran"}
{"id":7,"name":"SARL Atlas"}
/api/billing/clients/<client_id>/
Fiche et compte client : solde = (factures − versements) − (avoirs − remboursements), brouillons et annulées exclus, comme l'écran.
{"id":7,"name":"SARL Atlas","facture_total":"11900.00","facture_paid":"5000.00","solde":"6900.00"}
/api/billing/clients/<client_id>/
✏️ mode écriture requis
Met à jour les champs ENVOYÉS seulement. NIF, NIS, RC, AI et NIN passent par les validateurs de l'écran (400 si invalides).
{"city":"Alger","default_discount":"5"}
{"id":7,"city":"Alger","solde":"6900.00"}
/api/billing/clients/<client_id>/
✏️ mode écriture requis
Supprime un client sans document (sinon 409). Réservé au propriétaire, comme l'écran.
{"deleted":true}
/api/stock/products/
Produits du catalogue avec niveau de stock en temps réel — la brique d'une intégration e-commerce.
[{"id":12,"name":"Café 250g","sku":"CAF-250","sell_price":450.0,"tax_rate":19.0,"quantity":38.0}]
/api/stock/products/create/
✏️ mode écriture requis
Crée un produit (quota de produits du plan). opening_qty pose le stock initial au coût opening_cost (à défaut le prix d'achat) : c'est lui qui nourrit le CMUP.
{"name":"Peinture 20 L","sku":"PB-20","buy_price":"3000","sell_price":"4500","opening_qty":"12"}
{"id":13,"name":"Peinture 20 L","quantity":"12.000","cmup":"3000.0000"}
/api/stock/products/<product_id>/
Fiche produit, stock par dépôt et 5 dernières modifications.
{"id":13,"quantity":"12.000","stock_par_depot":[{"depot_id":2,"depot":"Oran","quantity":"12.000"}],"historique":[…]}
/api/stock/products/<product_id>/
✏️ mode écriture requis
Met à jour les champs ENVOYÉS (journalisés comme à l'écran). stock_target pose l'ajustement « Ajustement manuel → N ».
{"sell_price":"4800","stock_target":"10"}
{"id":13,"sell_price":"4800.00","quantity":"10.000"}
/api/stock/move/
✏️ mode écriture requis
Mouvement de stock : delta positif = entrée, négatif = sortie. Une sortie qui rendrait le stock négatif est refusée (mêmes règles que la caisse).
{"product_id":12,"delta":10,"reason":"Réception fournisseur"}
{"movement_id":901,"quantity":33.0}
/api/stock/movements/
Historique des mouvements de stock, du plus récent au plus ancien.
[{"id":901,"product_id":12,"type":"in","quantity_delta":"10.000","unit_cost":"300.0000","date":"2026-10-08"}]
/api/stock/depots/
Dépôts de la société.
[{"id":2,"name":"Oran","is_active":true}]
/api/stock/depots/<depot_id>/stock/
Quantités par produit dans un dépôt (règle mono-dépôt de l'écran Stock comprise).
{"depot_id":2,"depot":"Oran","stock":[{"product_id":12,"name":"Café 250g","quantity":"7.000"}]}
/api/stock/inventories/
Inventaires (sessions de comptage).
[{"id":4,"date":"2026-10-08","status":"counting","nb_lignes":120,"nb_comptees":80}]
/api/stock/inventories/create/
✏️ mode écriture requis
Ouvre un inventaire : le théorique de chaque produit est FIGÉ à l'ouverture, par le calcul de l'écran.
{"label":"Fin de mois","scope":"all","blind":true}
{"id":4,"status":"draft","lines":[{"product_id":12,"expected":null,"counted":null}]}
/api/stock/inventories/<inventory_id>/
Un inventaire et ses lignes (comptage aveugle : théorique et écart masqués jusqu'à la validation).
{"id":4,"lines":[{"product_id":12,"expected":"10.000","counted":"8.000","ecart":"-2.000"}]}
/api/stock/inventories/<inventory_id>/count/
✏️ mode écriture requis
Enregistre des quantités comptées. Toutes les lignes sont validées avant écriture ; inventaire validé : 409.
{"lines":[{"product_id":12,"counted":"8","motif":"casse"}]}
{"id":4,"status":"counting","lines":[…]}
/api/stock/inventories/<inventory_id>/validate/
✏️ mode écriture requis
Valide l'inventaire et pose les ajustements d'écart, UNE seule fois (seconde validation : 409).
{}
{"id":4,"status":"validated","ajustements":1}
/api/stock/suppliers/
Fournisseurs (liste paginée).
[{"id":3,"name":"Lafarge","phone":"021000000","nif":""}]
/api/stock/suppliers/create/
✏️ mode écriture requis
Crée un fournisseur.
{"name":"Lafarge","phone":"021 00 00 00"}
{"id":3,"name":"Lafarge"}
/api/stock/suppliers/<supplier_id>/
Un fournisseur.
{"id":3,"name":"Lafarge","city":"Alger"}
/api/stock/purchases/
Achats (bons d'achat et factures fournisseur) avec leur état de règlement.
[{"id":15,"number":"FA-77","status":"received","total_ttc":"11305.00","payment_status":"unpaid"}]
/api/stock/purchases/create/
✏️ mode écriture requis
Crée un achat. status=received (facture d'achat) entre la marchandise en stock par la réception de l'écran : conversion d'unités, CMUP, produit créé si la désignation est inconnue.
{"supplier_id":3,"status":"received","number":"FA-77","lines":[{"designation":"Ciment","quantity":"10","unit_price":"800"}]}
{"id":15,"status":"received","lignes_entrees_en_stock":1,"lines":[…]}
/api/stock/purchases/<purchase_id>/
Un achat avec ses lignes.
{"id":15,"lines":[{"designation":"Ciment","quantity":"10.000"}]}
/api/stock/purchases/<purchase_id>/status/
✏️ mode écriture requis
Change le statut ; « received » entre la marchandise en stock une seule fois (rejoué : rien ne bouge).
{"status":"received"}
{"id":15,"status":"received","lignes_entrees_en_stock":1}
/api/rh/employees/
Salariés de la société et leur fiche RH.
[{"id":21,"hr_id":9,"email":"karim.benali@acme.dz","nom":"Benali","prenom":"Karim","poste":"Magasinier","date_embauche":"2026-09-01"}]
/api/rh/employees/create/
✏️ mode écriture requis
Crée un salarié comme l'écran « Ajouter un employé » : identifiant et mot de passe générés s'ils manquent (affichés UNE fois), aucun module accordé.
{"nom":"Benali","prenom":"Karim","poste":"Magasinier","type_contrat":"cdi","salaire_base":"45000"}
{"id":21,"identifiant":"karim.benali@acme.dz","mot_de_passe":"Xy7…","note":"Mot de passe affiché une seule fois"}
/api/rh/employees/<employee_id>/
Un salarié.
{"id":21,"poste":"Magasinier","salaire_base":"45000.00"}
/api/rh/employees/<employee_id>/
✏️ mode écriture requis
Met à jour la fiche RH (champs ENVOYÉS seulement ; dates invraisemblables refusées).
{"poste":"Chef magasinier","nb_enfants":2}
{"id":21,"poste":"Chef magasinier"}
/api/rh/payslips/
Bulletins de paie (lecture seule : un bulletin s'établit à l'écran, où se vérifient barèmes, absences et avances).
[{"id":300,"employee_id":21,"mois":9,"annee":2026,"salaire_brut":"45000","irg":"…","salaire_net":"…"}]
/api/rh/payslips/<payslip_id>/
Un bulletin avec ses rubriques (gains, retenues), cotisations et net.
{"id":300,"salaire_net":"…","lignes":[{"label":"Prime de panier","type":"gain","montant":"3000.00"}]}
/api/rh/contracts/
Contrats et documents RH (le patron voit tout ; un employé, les siens et ceux partagés).
[{"id":5,"title":"CDI — Karim Benali","status":"finalized","language":"fr"}]
/api/rh/contracts/<contract_id>/
Un contrat : texte final et variables.
{"id":5,"body":"…","variables":{"salaire":"45000"}}
/api/rh/attendance/
Pointages bruts (pointeuses et saisies manuelles), 31 jours au plus ; un chef d'équipe ne voit que ses sites.
[{"id":7001,"employee_id":21,"timestamp":"2026-10-08T07:58:00+01:00","kind":"in","manual":false}]
/api/rh/advances/
Avances sur salaire.
[{"id":40,"employee_id":21,"montant":"3334.00","target_mois":11,"target_annee":2026,"status":"paid"}]
/api/rh/advances/create/
✏️ mode écriture requis
Enregistre une avance ; regulariser=true la répartit sur nb_mois à partir de start_mois/start_annee, par la fonction de l'écran.
{"employee_id":21,"montant":"10000","regulariser":true,"nb_mois":3,"start_mois":11,"start_annee":2026}
[{"id":40,"montant":"3334.00","target_mois":11},{"id":41,"montant":"3333.00","target_mois":12},{"id":42,"montant":"3333.00","target_mois":1}]
/api/enterprise/employees/
Plan Entreprise : liste tous les employés actifs avec leur rôle, poste et date d'embauche.
{"count":12,"employees":[{"id":1,"email":"ahmed@acme.dz","role":"employee","nom":"Benali","prenom":"Ahmed","poste":"Comptable"}]}
/api/enterprise/timesheets/
Plan Entreprise : suivi du temps de toutes les équipes sur une plage de dates (max 31 jours).
{"count":45,"from":"2025-01-01","to":"2025-01-31","entries":[{"id":101,"user_email":"ahmed@acme.dz","duration_seconds":30600}]}
/api/enterprise/leaves/
Plan Entreprise : demandes de congés avec filtrage par statut.
{"count":3,"leaves":[{"id":5,"employee":"sara@acme.dz","start_date":"2025-02-10","status":"approved"}]}
/api/enterprise/
Plan Entreprise : informations de l'entreprise, nombre d'employés, modules actifs.
{"company":"Acme SARL","employees":12,"modules":{"erp":true,"payroll":false},"api_version":"1.0"}
/api/webhooks/
✏️ mode écriture requis
Déclare une URL HTTPS à notifier (POST signé HMAC-SHA256, en-tête X-Almawarid-Signature). Événements : invoice.paid, invoice.status, client.created. Le secret n'est affiché qu'une fois.
{"url":"https://boutique.dz/hooks/almawarid","events":"invoice.paid"}
{"id":3,"url":"https://boutique.dz/hooks/almawarid","secret":"…affiché une seule fois…"}
/api/webhooks/
Liste des webhooks avec leur santé (dernier statut, échecs). Un webhook qui échoue 20 fois d'affilée se désactive seul.
[{"id":3,"url":"https://boutique.dz/hooks/almawarid","is_active":true,"last_status":"http 200","failure_count":0}]
/api/webhooks/<webhook_id>/
✏️ mode écriture requis
Supprime un webhook.
{"deleted":true}
Votre jeton et des exemples prêts à copier apparaissent une fois connecté.