Documentation API

API REST de CaledoCompta : clients, devis, factures, paiements, dépenses et boutique en ligne.

URL de base : https://VOTRE-COMPTE.caledocompta.com/api/v1

1 Authentification

Chaque requête s'authentifie par une clé API, dans l'entête Authorization. Une clé a les droits de l'utilisateur qui l'a créée et reste valable jusqu'à sa révocation.

Créez vos clés dans votre compte : Réglages › Documentation API. Une clé n'est affichée qu'une fois.
cURL
curl https://VOTRE-COMPTE.caledocompta.com/api/v1/me \
  -H "Authorization: Bearer VOTRE_CLE_API"
JavaScript
const BASE = "https://VOTRE-COMPTE.caledocompta.com/api/v1";
const token = process.env.CALEDOCOMPTA_API_KEY; // "caledocompta_key_..."

const me = await fetch(BASE + "/me", {
  headers: { "Authorization": "Bearer " + token }
}).then(r => r.json());
PHP
<?php
$base = "https://VOTRE-COMPTE.caledocompta.com/api/v1";
$key  = getenv("CALEDOCOMPTA_API_KEY"); // "caledocompta_key_..."

function caledocompta(string $method, string $path, ?array $body = null): array
{
    global $base, $key;
    $ch = curl_init($base . $path);
    curl_setopt_array($ch, [
        CURLOPT_CUSTOMREQUEST  => $method,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER     => ["Authorization: Bearer $key", "Content-Type: application/json", "Accept: application/json"],
    ]);
    if ($body !== null) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
    }
    $response = json_decode(curl_exec($ch), true);
    curl_close($ch);

    return $response;
}

$me = caledocompta("GET", "/me");
Gardez la clé secrète, jamais dans du code exécuté par le navigateur. Une clé révoquée est refusée (401).

2 Opérations de base

Créer un client, puis un devis ou une facture pour ce client.

POST /clients Créer un client

Crée la fiche client et son contact. Pour réutiliser un client existant, cherchez-le avec GET /clients?q=.

name requis texte
Max : 255 caractères Exemple : Acme Sarl
Nom du client ou de la société.
email email
Exemple : contact@example.com
Email du contact, utilisé pour envoyer devis et factures.
phone texte
Max : 40 caractères Exemple : +687 00 00 00
cURL
curl -X POST https://VOTRE-COMPTE.caledocompta.com/api/v1/clients \
  -H "Authorization: Bearer VOTRE_CLE_API" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Acme Sarl", "email": "contact@example.com", "phone": "+687 00 00 00" }'
JavaScript
await fetch(BASE + "/clients", {
  method: "POST",
  headers: { "Content-Type": "application/json", "Authorization": "Bearer " + token },
  body: JSON.stringify({ name: "Acme Sarl", email: "contact@example.com", phone: "+687 00 00 00" })
}).then(r => r.json());
PHP
$client = caledocompta("POST", "/clients", [
    "name"  => "Acme Sarl",
    "email" => "contact@example.com",
    "phone" => "+687 00 00 00",
]);
Réponse 201
{ "id": 42, "name": "Acme Sarl", "email": "contact@example.com", "phone": "+687 00 00 00" }
POST /estimates Créer un devis
clientId requis sans newClient entier
Exemple : 42
Id du client, renvoyé par POST /clients.
newClient objet
Crée le client au passage, si clientId est absent.
name requis texte
Max : 255 caractères
email email
title texte
Max : 255 caractères
Objet, affiché sous le numéro.
lines liste d'objets
Lignes du devis, dans l'ordre. Facultatif : sans ligne, le devis est créé vide ; sinon, la somme des lignes avant remise doit être supérieure à 0.
description requis texte
Max : 500 caractères Exemple : Prestation de conseil
Libellé de la ligne.
unitPrice nombre
Min : 0 Max : 99999999.99 Défaut : 0 Exemple : 10000
Prix unitaire HT.
quantity requis nombre
Min : 0.01 Max : 100000 Exemple : 1
tvaBucket texte
Valeurs : tgc22 · tgc11 · tgc6 · tgc3 · tgc0 Défaut : tgc22 Exemple : tgc22
Taux de TGC de la ligne.
unit texte
Max : 60 caractères Défaut : u
Unité affichée : h, jour, kg...
productId entier
Produit du catalogue lié à la ligne (GET /products).
type texte
Valeurs : plain · title · text Défaut : plain
title : titre de section, text : paragraphe de texte mis en forme. Leur prix, quantité et TGC sont ignorés.
date date
Format : AAAA-MM-JJ Défaut : aujourd'hui
expiryDate date
Format : AAAA-MM-JJ Défaut : aujourd'hui + délai des réglages (30 jours s'il est nul)
Date de validité.
discount objet
Remise sur le total HT.
type texte
Valeurs : percentage · amount
value nombre
Min : 0
Pourcentage (100 au plus) ou montant HT (le total au plus).
terms texte
Défaut : conditions des réglages
Conditions affichées en bas du document, texte mis en forme (gras, italique, listes). "" les retire.
notes texte
Note interne, jamais affichée au client.
422 : Client introuvable, somme des lignes nulle, ou montant supérieur à 99 999 999 F.
cURL
curl -X POST https://VOTRE-COMPTE.caledocompta.com/api/v1/estimates \
  -H "Authorization: Bearer VOTRE_CLE_API" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": 42,
    "lines": [
      { "description": "Prestation de conseil", "unitPrice": 10000, "quantity": 1, "tvaBucket": "tgc22" }
    ],
    "expiryDate": "2026-11-14"
  }'
JavaScript
await fetch(BASE + "/estimates", {
  method: "POST",
  headers: { "Content-Type": "application/json", "Authorization": "Bearer " + token },
  body: JSON.stringify({
    clientId: 42,
    lines: [
      { description: "Prestation de conseil", unitPrice: 10000, quantity: 1, tvaBucket: "tgc22" }
    ],
    expiryDate: "2026-11-14"
  })
}).then(r => r.json());
PHP
$estimate = caledocompta("POST", "/estimates", [
    "clientId"   => 42,
    "lines"      => [
        ["description" => "Prestation de conseil", "unitPrice" => 10000, "quantity" => 1, "tvaBucket" => "tgc22"],
    ],
    "expiryDate" => "2026-11-14",
]);
Réponse 201
{ "id": 108, "number": "DEV-108", "clientId": 42, "status": "sent", "subtotal": 10000, "total": 11600 }
POST /invoices Créer une facture

Mêmes champs que le devis, avec dueDate (échéance) au lieu de expiryDate.

422 : Client introuvable, somme des lignes nulle, ou montant supérieur à 99 999 999 F.
cURL
curl -X POST https://VOTRE-COMPTE.caledocompta.com/api/v1/invoices \
  -H "Authorization: Bearer VOTRE_CLE_API" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": 42,
    "lines": [
      { "description": "Prestation de conseil", "unitPrice": 10000, "quantity": 1, "tvaBucket": "tgc22" }
    ],
    "dueDate": "2026-11-14"
  }'
JavaScript
await fetch(BASE + "/invoices", {
  method: "POST",
  headers: { "Content-Type": "application/json", "Authorization": "Bearer " + token },
  body: JSON.stringify({
    clientId: 42,
    lines: [
      { description: "Prestation de conseil", unitPrice: 10000, quantity: 1, tvaBucket: "tgc22" }
    ],
    dueDate: "2026-11-14"
  })
}).then(r => r.json());
PHP
$invoice = caledocompta("POST", "/invoices", [
    "clientId" => 42,
    "lines"    => [
        ["description" => "Prestation de conseil", "unitPrice" => 10000, "quantity" => 1, "tvaBucket" => "tgc22"],
    ],
    "dueDate"  => "2026-11-14",
]);

3 Boutique en ligne (WooCommerce)

La boutique lit le catalogue et le stock de CaledoCompta, puis y envoie ses commandes : chacune devient une facture et décrémente le stock. Les produits sont reliés par leur référence (SKU).

Module activé sur demande : contactez-nous.
GET /shop/products Lire le catalogue et le stock

Les produits du catalogue avec leur prix, leur stock, leur catégorie, leurs descriptions et leurs images. Une synchronisation régulière ne demande que les produits modifiés depuis la précédente.

updatedSince date et heure
Format : ISO 8601 Exemple : 2026-09-23T08:00:00+11:00
Seulement les produits modifiés depuis cette date (stock et images compris).
sku texte
Max : 100 caractères Exemple : MIEL-500
Un seul produit, par sa référence.
hasSku entier
Valeurs : 0 · 1 Exemple : 1
1 : seulement les produits qui ont une référence, c'est-à-dire ceux vendus en ligne.
page entier
Min : 1 Défaut : 1
Numéro de page.
perPage entier
Min : 1 Max : 200 Défaut : 100
Éléments par page.
À savoir
stock et lowStockAlert valent null si le stock n'est pas suivi. Le stock est en unités entières. priceTtc est arrondi à la précision du compte (franc, ou centime pour un compte à 2 décimales).
Correspondance WooCommerce : priceTtc → regular_price, shortDescription → short_description, category.name → categories, images[].url → images[].src, stock → stock_quantity. Les URL d'images sont publiques.
Comparez régulièrement avec le catalogue complet pour détecter les produits retirés.
403 : Module boutique non activé sur ce compte (module_disabled).
cURL
curl "https://VOTRE-COMPTE.caledocompta.com/api/v1/shop/products?hasSku=1&updatedSince=2026-09-23T08:00:00+11:00" \
  -H "Authorization: Bearer VOTRE_CLE_API"
JavaScript
const { data } = await fetch(BASE + "/shop/products?hasSku=1&updatedSince=" + encodeURIComponent(lastSync), {
  headers: { "Authorization": "Bearer " + token }
}).then(r => r.json());
PHP
$page = caledocompta("GET", "/shop/products?hasSku=1&updatedSince=" . urlencode($lastSync));

foreach ($page["data"] as $product) {
    // créer ou mettre à jour le produit de la boutique ayant ce SKU
}
Réponse 200
{
  "data": [
    { "id": 12, "sku": "MIEL-500", "name": "Miel de Nouvelle-Calédonie 500 g", "unit": "pot",
      "category": { "id": 14, "name": "Épicerie fine" },
      "shortDescription": "Miel de fleurs récolté à La Foa.",
      "description": "<p>Miel cru, non chauffé, mis en pot à la main.</p>",
      "images": [
        { "id": 301, "url": "https://VOTRE-COMPTE.caledocompta.com/…/miel-500.jpg",
          "thumbnailUrl": "https://VOTRE-COMPTE.caledocompta.com/…/miel-500-thumb.jpg", "name": "miel-500.jpg", "position": 0 }
      ],
      "priceHt": 1500, "tvaRate": 3, "priceTtc": 1545,
      "stockManaged": true, "stock": 42, "lowStockAlert": 5,
      "updatedAt": "2026-09-23T09:14:02+11:00" }
  ],
  "page": 1, "perPage": 100, "total": 1
}
POST /shop/orders Facturer une commande de la boutique

Retrouve ou crée le client (par email), crée la facture au prix payé et, si la commande est payée, le paiement. Le stock est décrémenté.

reference requis texte
Max : 100 caractères Caractères : A-Z a-z 0-9 . _ - Exemple : 1042
Numéro de la commande dans la boutique. Renvoyer une commande déjà reçue ne crée rien de plus.
source texte
Max : 50 caractères Défaut : woocommerce
Boutique d'origine. Avec reference, identifie la commande.
date date
Format : AAAA-MM-JJ Défaut : aujourd'hui
Date de la facture. Un horodatage UTC est ramené au jour de Nouméa. Échéance : le même jour si la commande est payée, sinon cette date + le délai de paiement des réglages (30 jours s'il est nul).
customer requis objet
L'acheteur. Un client existant avec le même email est réutilisé, sinon il est créé.
email requis email
Max : 255 caractères Exemple : client@example.com
company texte
Max : 255 caractères
Nom du client. À défaut : prénom et nom, puis l'email.
firstName texte
Max : 100 caractères Exemple : Teva
Prénom du contact.
lastName texte
Max : 100 caractères Exemple : Exemple
Nom du contact.
phone texte
Max : 40 caractères Exemple : +687 00 00 00
address objet
Adresse de facturation.
street texte
Max : 255 caractères Exemple : Rue du Commerce
city texte
Max : 100 caractères Exemple : Nouméa
zip texte
Max : 20 caractères Exemple : 98800
country texte
Max : 100 caractères
lines requis liste d'objets
Min : 1 élément
Les articles commandés, dans l'ordre de la facture.
sku requis texte
Max : 100 caractères Exemple : MIEL-500
Référence du produit dans CaledoCompta, majuscules indifférentes. Une référence inconnue refuse toute la commande.
quantity requis nombre
Min : 0.01 Max : 100000 Exemple : 2
Nombre entier si le stock du produit est suivi.
unitPriceTtc requis nombre
Min : 0 Max : 99999999 Exemple : 1545
Prix unitaire TTC réellement payé, coupons déduits. Le HT est recalculé avec le taux de TGC du produit.
name texte
Max : 500 caractères Défaut : la désignation du produit
Libellé de la ligne sur la facture.
shipping objet
Frais de livraison, ajoutés en dernière ligne de la facture.
amountTtc requis avec shipping nombre
Min : 0 Max : 99999999 Exemple : 1000
Montant TTC payé.
tvaRate requis si montant > 0 entier
Valeurs : 0 · 3 · 6 · 11 · 22 Exemple : 11
Taux de TGC des frais, en %.
label texte
Max : 255 caractères Défaut : Frais de livraison Exemple : Livraison Nouméa
payment requis objet
status requis texte
Valeurs : paid · pending Exemple : paid
paid : la facture est soldée. pending : elle reste due, à payer plus tard avec POST /shop/orders/{reference}/payment.
method texte
Max : 60 caractères Défaut : Boutique en ligne Exemple : Carte bancaire
Moyen de paiement affiché sur le paiement.
transactionId texte
Max : 100 caractères
Identifiant du paiement chez le prestataire, affiché sur le paiement.
date date
Format : AAAA-MM-JJ Défaut : aujourd'hui
totalTtc nombre
Min : 0 Exemple : 4090
Total payé sur la boutique. Il est comparé au total de la facture dans totals.
notes texte
Max : 2000 caractères
Note ajoutée à la facture.
À savoir
Stock : chaque réponse (réception, paiement, annulation) renvoie stock, le stock à jour des produits de la commande dont le stock est suivi. Reportez-le dans la boutique, qui décrémente aussi son propre stock.
Une commande déjà reçue renvoie 200 et "duplicate": true : un envoi peut être rejoué sans risque.
paymentRecorded indique si le paiement a été enregistré. S'il vaut false, enregistrez-le avec POST /shop/orders/{reference}/payment.
403 : Module boutique non activé sur ce compte (module_disabled).
422 : Référence de produit inconnue, quantité non entière pour un produit dont le stock est suivi, total nul ou taux de TGC des frais manquant : rien n'est créé.
409 : Opération impossible dans l'état actuel de la commande : réessayez plus tard ou consultez GET /shop/orders/{reference}.
cURL
curl -X POST https://VOTRE-COMPTE.caledocompta.com/api/v1/shop/orders \
  -H "Authorization: Bearer VOTRE_CLE_API" \
  -H "Content-Type: application/json" \
  -d '{
    "reference": "1042",
    "customer": { "email": "client@example.com", "firstName": "Teva", "lastName": "Exemple",
                  "phone": "+687 00 00 00", "address": { "street": "Rue du Commerce", "city": "Nouméa", "zip": "98800" } },
    "lines": [ { "sku": "MIEL-500", "quantity": 2, "unitPriceTtc": 1545 } ],
    "shipping": { "label": "Livraison Nouméa", "amountTtc": 1000, "tvaRate": 11 },
    "payment": { "status": "paid", "method": "Carte bancaire", "transactionId": "pi_3Q..." },
    "totalTtc": 4090
  }'
JavaScript
const order = await fetch(BASE + "/shop/orders", {
  method: "POST",
  headers: { "Content-Type": "application/json", "Authorization": "Bearer " + token },
  body: JSON.stringify({
    reference: String(wcOrder.id),
    customer: { email: wcOrder.billing.email, firstName: wcOrder.billing.first_name, lastName: wcOrder.billing.last_name },
    lines: wcOrder.line_items.map(l => ({ sku: l.sku, quantity: l.quantity, unitPriceTtc: (Number(l.total) + Number(l.total_tax)) / l.quantity })),
    shipping: { amountTtc: Number(wcOrder.shipping_total) + Number(wcOrder.shipping_tax), tvaRate: 11 }, // taux de vos frais de livraison
    payment: { status: wcOrder.date_paid ? "paid" : "pending", method: (wcOrder.payment_method_title || "").slice(0, 60) },
    totalTtc: Number(wcOrder.total)
  })
}).then(r => r.json());
PHP
// $wcOrder : la commande WooCommerce (JSON de son API REST, décodé)
$order = caledocompta("POST", "/shop/orders", [
    "reference" => (string) $wcOrder["id"],
    "customer"  => [
        "email"     => $wcOrder["billing"]["email"],
        "firstName" => $wcOrder["billing"]["first_name"],
        "lastName"  => $wcOrder["billing"]["last_name"],
    ],
    "lines"     => array_map(fn ($l) => [
        "sku"          => $l["sku"],
        "quantity"     => $l["quantity"],
        "unitPriceTtc" => ($l["total"] + $l["total_tax"]) / $l["quantity"],
    ], $wcOrder["line_items"]),
    "shipping"  => [
        "amountTtc" => $wcOrder["shipping_total"] + $wcOrder["shipping_tax"],
        "tvaRate"   => 11, // taux de vos frais de livraison
    ],
    "payment"   => [
        "status" => $wcOrder["date_paid"] ? "paid" : "pending",
        "method" => mb_substr((string) $wcOrder["payment_method_title"], 0, 60),
    ],
    "totalTtc"  => (float) $wcOrder["total"],
]);
Réponse 201
{
  "source": "woocommerce", "reference": "1042", "status": "invoiced", "clientId": 57,
  "invoice": { "id": 318, "number": "FACT-318", "status": "paid", "total": 4090, ... },
  "creditNote": null,
  "totals": { "invoice": 4090, "site": 4090, "difference": 0 },
  "stock": [ { "sku": "MIEL-500", "stock": 40 } ],
  "paymentRecorded": true
}
Suivre, payer ou annuler une commande
GET/shop/orders/{reference}état, facture, avoir
POST/shop/orders/{reference}/cancelannulation totale
POST/shop/orders/{reference}/paymentcommande payée après coup · method, transactionId, date optionnels
L'annulation crée un avoir et remet le stock. Le remboursement se fait dans votre moyen de paiement.

4 Référence des endpoints

Toutes les routes, par ressource. Cliquez sur une route pour voir ses champs et sa réponse.

Compte 1
GET /me Vérifier la clé

L'utilisateur de la clé et le compte. Le bon appel pour tester une clé.

Réponse 200
JSON
{
    "user": {
        "id": 1,
        "firstName": "Teva",
        "lastName": "Exemple",
        "email": "client@example.com",
        "role": "Administrateur"
    },
    "account": {
        "name": "Ma société",
        "tvaEnabled": true,
        "decimals": 0
    }
}
Clients 4
GET /clients Lister les clients

Les clients actifs, par ordre alphabétique (1 000 au plus).

q texte
Exemple : acme
Recherche dans le nom du client.
Réponse 200
JSON
{
    "data": [
        {
            "id": 42,
            "name": "Acme Sarl",
            "email": "contact@example.com",
            "outstanding": 0,
            "dueCount": 0,
            "invoiceCount": 1,
            "totalBilled": 11600
        }
    ]
}
POST /clients Créer un client

Crée la fiche client et son contact. Pour réutiliser un client existant, cherchez-le avec GET /clients?q=.

name requis texte
Max : 255 caractères Exemple : Acme Sarl
Nom du client ou de la société.
email email
Exemple : contact@example.com
Email du contact, utilisé pour envoyer devis et factures.
phone texte
Max : 40 caractères Exemple : +687 00 00 00
Réponse 201
JSON
{
    "id": 42,
    "name": "Acme Sarl",
    "email": "contact@example.com",
    "phone": "+687 00 00 00"
}
GET /clients/{id} Détail d'un client

La fiche, le reste dû, et l'historique des factures, devis et paiements.

id requis entier
Exemple : 42
Identifiant du client.
404 : Client introuvable.
Réponse 200
JSON
{
    "id": 42,
    "name": "Acme Sarl",
    "email": "contact@example.com",
    "phone": "+687 00 00 00",
    "website": null,
    "vat": null,
    "city": "Nouméa",
    "zip": "98800",
    "country": null,
    "outstanding": 0,
    "invoices": [
        {
            "id": 318,
            "number": "FACT-318",
            "date": "2026-09-23",
            "total": 11600,
            "status": "paid"
        }
    ],
    "estimates": [
        {
            "id": 108,
            "number": "DEV-108",
            "date": "2026-09-20",
            "total": 11600,
            "status": "accepted"
        }
    ],
    "payments": [
        {
            "id": 77,
            "date": "2026-09-23",
            "amount": 11600,
            "method": "Virement",
            "invoiceNumber": "FACT-318"
        }
    ]
}
PUT /clients/{id} Modifier un client

Seuls les champs envoyés changent ; un champ envoyé à null est effacé.

Paramètres
id requis entier
Exemple : 42
Identifiant du client.
Corps JSON
name requis texte
Max : 255 caractères Exemple : Acme Sarl
email email
Email du contact principal.
phone texte
Max : 60 caractères
city texte
Max : 120 caractères
zip texte
Max : 30 caractères
country texte
Max : 120 caractères
À savoir
404 : Client introuvable.
422 : L'email n'a pas pu être enregistré pour ce client.
Réponse 200
JSON
{
    "id": 42,
    "name": "Acme Sarl",
    "email": "contact@example.com",
    "phone": "+687 00 00 00",
    "website": null,
    "vat": null,
    "city": "Nouméa",
    "zip": "98800",
    "country": null,
    "outstanding": 0,
    "invoices": [
        {
            "id": 318,
            "number": "FACT-318",
            "date": "2026-09-23",
            "total": 11600,
            "status": "paid"
        }
    ],
    "estimates": [
        {
            "id": 108,
            "number": "DEV-108",
            "date": "2026-09-20",
            "total": 11600,
            "status": "accepted"
        }
    ],
    "payments": [
        {
            "id": 77,
            "date": "2026-09-23",
            "amount": 11600,
            "method": "Virement",
            "invoiceNumber": "FACT-318"
        }
    ]
}
Devis 7
GET /estimates Lister les devis

Les devis, du plus récent au plus ancien (1 000 au plus), sans leurs lignes.

Statuts : draft, sent, accepted, declined, revised, expired.
Réponse 200
JSON
{
    "data": [
        {
            "id": 108,
            "number": "DEV-108",
            "clientId": 42,
            "clientName": "Acme Sarl",
            "title": "",
            "status": "sent",
            "subtotal": 10000,
            "discount": {
                "type": null,
                "percentage": 0,
                "amount": 0
            },
            "tvaTotal": 2200,
            "total": 12200,
            "createdAt": "2026-09-28T08:16:30+11:00",
            "date": "2026-09-28",
            "expiryDate": "2026-10-28",
            "lines": []
        }
    ]
}
POST /estimates Créer un devis
clientId requis sans newClient entier
Exemple : 42
Id du client, renvoyé par POST /clients.
newClient objet
Crée le client au passage, si clientId est absent.
name requis texte
Max : 255 caractères
email email
title texte
Max : 255 caractères
Objet, affiché sous le numéro.
lines liste d'objets
Lignes du devis, dans l'ordre. Facultatif : sans ligne, le devis est créé vide ; sinon, la somme des lignes avant remise doit être supérieure à 0.
description requis texte
Max : 500 caractères Exemple : Prestation de conseil
Libellé de la ligne.
unitPrice nombre
Min : 0 Max : 99999999.99 Défaut : 0 Exemple : 10000
Prix unitaire HT.
quantity requis nombre
Min : 0.01 Max : 100000 Exemple : 1
tvaBucket texte
Valeurs : tgc22 · tgc11 · tgc6 · tgc3 · tgc0 Défaut : tgc22 Exemple : tgc22
Taux de TGC de la ligne.
unit texte
Max : 60 caractères Défaut : u
Unité affichée : h, jour, kg...
productId entier
Produit du catalogue lié à la ligne (GET /products).
type texte
Valeurs : plain · title · text Défaut : plain
title : titre de section, text : paragraphe de texte mis en forme. Leur prix, quantité et TGC sont ignorés.
date date
Format : AAAA-MM-JJ Défaut : aujourd'hui
expiryDate date
Format : AAAA-MM-JJ Défaut : aujourd'hui + délai des réglages (30 jours s'il est nul)
Date de validité.
discount objet
Remise sur le total HT.
type texte
Valeurs : percentage · amount
value nombre
Min : 0
Pourcentage (100 au plus) ou montant HT (le total au plus).
terms texte
Défaut : conditions des réglages
Conditions affichées en bas du document, texte mis en forme (gras, italique, listes). "" les retire.
notes texte
Note interne, jamais affichée au client.
422 : Client introuvable, somme des lignes nulle, ou montant supérieur à 99 999 999 F.
Réponse 201
JSON
{
    "id": 108,
    "number": "DEV-108",
    "clientId": 42,
    "clientName": "Acme Sarl",
    "title": "",
    "status": "sent",
    "subtotal": 10000,
    "discount": {
        "type": null,
        "percentage": 0,
        "amount": 0
    },
    "tvaTotal": 2200,
    "total": 12200,
    "createdAt": "2026-09-28T08:16:30+11:00",
    "date": "2026-09-28",
    "expiryDate": "2026-10-28",
    "lines": [
        {
            "id": 19,
            "productId": null,
            "description": "Prestation de conseil",
            "unitPrice": 10000,
            "unitPriceExact": 10000,
            "quantity": 1,
            "unit": "u",
            "tvaBucket": "tgc22",
            "lineTotal": 10000
        }
    ],
    "tvaBreakdown": [
        {
            "key": "tgc22",
            "label": "TGC 22 %",
            "rate": 22,
            "amount": 2200
        }
    ],
    "terms": "<p>Mauruuru pour votre confiance.</p>",
    "hasSections": false,
    "emails": []
}
GET /estimates/{id} Détail d'un devis

Le devis avec ses lignes, le détail de la TGC et les emails envoyés.

id requis entier
Exemple : 42
Identifiant du devis.
sections booléen
1 : inclut aussi les lignes de titre et de texte.
404 : Devis introuvable.
Réponse 200
JSON
{
    "id": 108,
    "number": "DEV-108",
    "clientId": 42,
    "clientName": "Acme Sarl",
    "title": "",
    "status": "sent",
    "subtotal": 10000,
    "discount": {
        "type": null,
        "percentage": 0,
        "amount": 0
    },
    "tvaTotal": 2200,
    "total": 12200,
    "createdAt": "2026-09-28T08:16:30+11:00",
    "date": "2026-09-28",
    "expiryDate": "2026-10-28",
    "lines": [
        {
            "id": 19,
            "productId": null,
            "description": "Prestation de conseil",
            "unitPrice": 10000,
            "unitPriceExact": 10000,
            "quantity": 1,
            "unit": "u",
            "tvaBucket": "tgc22",
            "lineTotal": 10000
        }
    ],
    "tvaBreakdown": [
        {
            "key": "tgc22",
            "label": "TGC 22 %",
            "rate": 22,
            "amount": 2200
        }
    ],
    "terms": "<p>Mauruuru pour votre confiance.</p>",
    "hasSections": false,
    "emails": []
}
GET /estimates/{id}/pdf Télécharger le PDF

Le devis en PDF (application/pdf), tel que l'imprime le logiciel.

id requis entier
Exemple : 42
Identifiant du devis.
404 : Devis introuvable.
Réponse 200

Fichier application/pdf.

GET /estimates/{id}/share Obtenir le lien public

Un lien à envoyer au client pour voir et télécharger le devis, sans compte.

id requis entier
Exemple : 42
Identifiant du devis.
404 : Devis introuvable.
Réponse 200
JSON
{
    "shareUrl": "https://VOTRE-COMPTE.caledocompta.com/…"
}
POST /estimates/{id}/send Envoyer par email

Envoie le devis en PDF à l'email du client. Le statut du devis ne change pas.

id requis entier
Exemple : 42
Identifiant du devis.
À savoir
404 : Devis introuvable.
422 : Le client n'a pas d'email (no_recipient).
Réponse 200
JSON
{
    "ok": true,
    "status": "sent"
}
POST /estimates/{id}/convert Convertir en facture

Crée la facture du devis, datée du jour ; le devis est conservé. Si le devis a déjà été converti, renvoie la même facture (200).

id requis entier
Exemple : 42
Identifiant du devis.
404 : Devis introuvable.
Réponse 201
JSON
{
    "id": 319,
    "number": "FACT-319"
}
Réponse 200 : Devis déjà converti : la facture existante.
JSON
{
    "id": 319,
    "number": "FACT-319"
}
Factures 7
GET /invoices Lister les factures

Les factures, de la plus récente à la plus ancienne, avec le payé (paid) et le reste dû (balance), sans leurs lignes.

status texte
Exemple : due,overdue,part_paid
Un ou plusieurs statuts, séparés par des virgules : draft, due, overdue, part_paid, paid, credit.
clientId entier
Exemple : 42
Les factures de ce client.
dateFrom date
Format : AAAA-MM-JJ
Date de facture, à partir de ce jour inclus.
dateTo date
Format : AAAA-MM-JJ
Date de facture, jusqu'à ce jour inclus.
updatedSince date et heure
Format : ISO 8601 Exemple : 2026-09-28T00:00:00+11:00
Les factures modifiées ou payées depuis cet instant. Le fuseau de la date est respecté.
page entier
Min : 1 Défaut : 1
Numéro de page.
perPage entier
Min : 1 Max : 1000 Défaut : 1000
Éléments par page.
À savoir
Statuts : draft, due, overdue, part_paid, paid, credit (avoir).
Pour suivre les règlements : appelez régulièrement GET /invoices?updatedSince= avec l'instant de votre appel précédent.
Réponse 200
JSON
{
    "data": [
        {
            "id": 318,
            "number": "FACT-318",
            "clientId": 42,
            "clientName": "Acme Sarl",
            "title": "",
            "status": "due",
            "subtotal": 10000,
            "discount": {
                "type": null,
                "percentage": 0,
                "amount": 0
            },
            "tvaTotal": 2200,
            "total": 12200,
            "createdAt": "2026-09-28T08:16:30+11:00",
            "date": "2026-09-28",
            "updatedAt": "2026-09-28T08:16:30+11:00",
            "dueDate": "2026-10-28",
            "lines": [],
            "paid": 0,
            "balance": 12200
        }
    ],
    "page": 1,
    "perPage": 100,
    "total": 1
}
POST /invoices Créer une facture
Paramètres
Idempotency-Key texte
Max : 191 caractères Exemple : 6f1c2a0e-8d3b-4c55-9a7e-2b1f0c9d4e21
Entête. Rejouer l'appel avec la même clé ne crée rien de plus. Voir Conventions › Idempotence.
Corps JSON
clientId requis sans newClient entier
Exemple : 42
Id du client, renvoyé par POST /clients.
newClient objet
Crée le client au passage, si clientId est absent.
name requis texte
Max : 255 caractères
email email
title texte
Max : 255 caractères
Objet, affiché sous le numéro.
lines liste d'objets
Lignes de la facture, dans l'ordre. Facultatif : sans ligne, la facture est créée vide ; sinon, la somme des lignes avant remise doit être supérieure à 0.
description requis texte
Max : 500 caractères Exemple : Prestation de conseil
Libellé de la ligne.
unitPrice nombre
Min : 0 Max : 99999999.99 Défaut : 0 Exemple : 10000
Prix unitaire HT.
quantity requis nombre
Min : 0.01 Max : 100000 Exemple : 1
tvaBucket texte
Valeurs : tgc22 · tgc11 · tgc6 · tgc3 · tgc0 Défaut : tgc22 Exemple : tgc22
Taux de TGC de la ligne.
unit texte
Max : 60 caractères Défaut : u
Unité affichée : h, jour, kg...
productId entier
Produit du catalogue lié à la ligne (GET /products).
type texte
Valeurs : plain · title · text Défaut : plain
title : titre de section, text : paragraphe de texte mis en forme. Leur prix, quantité et TGC sont ignorés.
date date
Format : AAAA-MM-JJ Défaut : aujourd'hui
dueDate date
Format : AAAA-MM-JJ Défaut : aujourd'hui + délai des réglages (30 jours s'il est nul)
Date d'échéance.
discount objet
Remise sur le total HT.
type texte
Valeurs : percentage · amount
value nombre
Min : 0
Pourcentage (100 au plus) ou montant HT (le total au plus).
terms texte
Défaut : conditions des réglages
Conditions affichées en bas du document, texte mis en forme (gras, italique, listes). "" les retire.
notes texte
Note interne, jamais affichée au client.
422 : Client introuvable, somme des lignes nulle, ou montant supérieur à 99 999 999 F.
Réponse 201
JSON
{
    "id": 318,
    "number": "FACT-318",
    "clientId": 42,
    "clientName": "Acme Sarl",
    "title": "",
    "status": "due",
    "subtotal": 10000,
    "discount": {
        "type": null,
        "percentage": 0,
        "amount": 0
    },
    "tvaTotal": 2200,
    "total": 12200,
    "createdAt": "2026-09-28T08:16:30+11:00",
    "date": "2026-09-28",
    "updatedAt": "2026-09-28T08:16:30+11:00",
    "dueDate": "2026-10-28",
    "lines": [
        {
            "id": 19,
            "productId": null,
            "description": "Prestation de conseil",
            "unitPrice": 10000,
            "unitPriceExact": 10000,
            "quantity": 1,
            "unit": "u",
            "tvaBucket": "tgc22",
            "lineTotal": 10000
        }
    ],
    "tvaBreakdown": [
        {
            "key": "tgc22",
            "label": "TGC 22 %",
            "rate": 22,
            "amount": 2200
        }
    ],
    "terms": "<p>Mauruuru pour votre confiance.</p>",
    "hasSections": false,
    "payments": [],
    "paid": 0,
    "balance": 12200,
    "emails": []
}
GET /invoices/{id} Détail d'une facture

La facture avec ses lignes, le détail de la TGC, les paiements et les emails envoyés.

id requis entier
Exemple : 42
Identifiant de la facture.
sections booléen
1 : inclut aussi les lignes de titre et de texte.
404 : Facture introuvable.
Réponse 200
JSON
{
    "id": 318,
    "number": "FACT-318",
    "clientId": 42,
    "clientName": "Acme Sarl",
    "title": "",
    "status": "due",
    "subtotal": 10000,
    "discount": {
        "type": null,
        "percentage": 0,
        "amount": 0
    },
    "tvaTotal": 2200,
    "total": 12200,
    "createdAt": "2026-09-28T08:16:30+11:00",
    "date": "2026-09-28",
    "updatedAt": "2026-09-28T08:16:30+11:00",
    "dueDate": "2026-10-28",
    "lines": [
        {
            "id": 19,
            "productId": null,
            "description": "Prestation de conseil",
            "unitPrice": 10000,
            "unitPriceExact": 10000,
            "quantity": 1,
            "unit": "u",
            "tvaBucket": "tgc22",
            "lineTotal": 10000
        }
    ],
    "tvaBreakdown": [
        {
            "key": "tgc22",
            "label": "TGC 22 %",
            "rate": 22,
            "amount": 2200
        }
    ],
    "terms": "<p>Mauruuru pour votre confiance.</p>",
    "hasSections": false,
    "payments": [],
    "paid": 0,
    "balance": 12200,
    "emails": []
}
GET /invoices/{id}/pdf Télécharger le PDF

La facture en PDF (application/pdf).

id requis entier
Exemple : 42
Identifiant de la facture.
404 : Facture introuvable.
Réponse 200

Fichier application/pdf.

GET /invoices/{id}/share Obtenir le lien public

Un lien à envoyer au client pour voir et télécharger la facture, sans compte.

id requis entier
Exemple : 42
Identifiant de la facture.
404 : Facture introuvable.
Réponse 200
JSON
{
    "shareUrl": "https://VOTRE-COMPTE.caledocompta.com/…"
}
POST /invoices/{id}/send Envoyer par email

Envoie la facture en PDF à l'email du client.

id requis entier
Exemple : 42
Identifiant de la facture.
À savoir
404 : Facture introuvable.
422 : Le client n'a pas d'email (no_recipient).
Réponse 200
JSON
{
    "ok": true,
    "status": "due"
}
POST /invoices/{id}/credit Annuler par un avoir

Pour annuler une facture émise, créez son avoir : il porte ses propres numéro et date. Renvoie l'avoir.

id requis entier
Exemple : 42
Identifiant de la facture.
Idempotency-Key texte
Max : 191 caractères Exemple : 6f1c2a0e-8d3b-4c55-9a7e-2b1f0c9d4e21
Entête. Rejouer l'appel avec la même clé ne crée rien de plus. Voir Conventions › Idempotence.
À savoir
L'avoir apparaît dans GET /invoices avec le statut credit et des montants négatifs.
404 : Facture introuvable.
422 : La facture est déjà un avoir.
Réponse 201
JSON
{
    "id": 319,
    "number": "FACT-319",
    "clientId": 42,
    "clientName": "Acme Sarl",
    "title": "",
    "status": "credit",
    "subtotal": -10000,
    "discount": {
        "type": null,
        "percentage": 0,
        "amount": 0
    },
    "tvaTotal": -2200,
    "total": -12200,
    "createdAt": "2026-09-30T09:12:04+11:00",
    "date": "2026-09-30",
    "updatedAt": "2026-09-30T09:12:04+11:00",
    "dueDate": "2026-10-28",
    "lines": [
        {
            "id": 20,
            "productId": null,
            "description": "Prestation de conseil",
            "unitPrice": 10000,
            "unitPriceExact": 10000,
            "quantity": -1,
            "unit": "u",
            "tvaBucket": "tgc22",
            "lineTotal": -10000
        }
    ],
    "tvaBreakdown": [
        {
            "key": "tgc22",
            "label": "TGC 22 %",
            "rate": 22,
            "amount": -2200
        }
    ],
    "terms": "<p>Mauruuru pour votre confiance.</p>",
    "hasSections": false,
    "payments": [],
    "paid": 0,
    "balance": 0,
    "emails": []
}
Paiements & dépenses 4
GET /payments Lister les paiements

Les paiements reçus, du plus récent au plus ancien.

invoiceId entier
Exemple : 318
Les paiements de cette facture.
clientId entier
Exemple : 42
Les paiements de ce client.
dateFrom date
Format : AAAA-MM-JJ
Date du paiement, à partir de ce jour inclus.
dateTo date
Format : AAAA-MM-JJ
Date du paiement, jusqu'à ce jour inclus.
updatedSince date et heure
Format : ISO 8601 Exemple : 2026-09-28T00:00:00+11:00
Les paiements enregistrés ou modifiés depuis cet instant.
page entier
Min : 1 Défaut : 1
Numéro de page.
perPage entier
Min : 1 Max : 1000 Défaut : 100
Éléments par page.
Un paiement supprimé disparaît de cette liste ; sa facture remonte dans GET /invoices?updatedSince= avec son nouveau reste dû.
Réponse 200
JSON
{
    "data": [
        {
            "id": 77,
            "invoiceId": 318,
            "invoiceNumber": "FACT-318",
            "clientId": 42,
            "date": "2026-09-30",
            "amount": 11600,
            "method": "Virement",
            "notes": null,
            "createdAt": "2026-09-30T09:05:41+11:00",
            "updatedAt": "2026-09-30T09:05:41+11:00"
        }
    ],
    "page": 1,
    "perPage": 100,
    "total": 1
}
POST /payments Enregistrer un paiement

Un paiement reçu sur une facture ; son statut est recalculé (payée, partiellement payée).

Paramètres
Idempotency-Key texte
Max : 191 caractères Exemple : 6f1c2a0e-8d3b-4c55-9a7e-2b1f0c9d4e21
Entête. Rejouer l'appel avec la même clé ne crée rien de plus. Voir Conventions › Idempotence.
Corps JSON
invoiceId requis entier
Exemple : 318
amount requis nombre
Min : 1 Max : 99999999 Exemple : 11600
Montant reçu, arrondi au franc.
date date
Format : AAAA-MM-JJ Défaut : aujourd'hui
method texte
Max : 60 caractères Défaut : Espèces Exemple : Virement
notes texte
Max : 1000 caractères
À savoir
status : le statut de la facture après le paiement (paid, part_paid...).
404 : Facture introuvable.
Réponse 201
JSON
{
    "ok": true,
    "invoiceId": 318,
    "status": "paid"
}
GET /expenses Lister les dépenses

Les dépenses créées par l'utilisateur de la clé, de la plus récente à la plus ancienne (1 000 au plus).

Réponse 200
JSON
{
    "data": [
        {
            "id": 55,
            "amount": 12200,
            "tva": {
                "tgc22": 2200
            },
            "title": "Fournitures de bureau",
            "supplierId": null,
            "supplierName": null,
            "categoryId": 3,
            "clientId": null,
            "date": "2026-09-20",
            "paymentStatus": "paid",
            "paymentMethod": "Carte bancaire",
            "paymentDate": "2026-09-20",
            "dueDate": null,
            "notes": null,
            "attachmentId": null,
            "attachmentUrl": null,
            "attachmentType": null,
            "attachmentName": null,
            "createdAt": "2026-09-20T10:02:11+11:00"
        }
    ]
}
POST /expenses Créer une dépense
amount requis nombre
Min : -99999999 Max : 99999999 Exemple : 11600
Montant TTC payé. Négatif pour un avoir fournisseur.
date requis date
Format : AAAA-MM-JJ Exemple : 2026-09-20
title texte
Max : 255 caractères Exemple : Fournitures de bureau
Libellé de la dépense.
tva objet
TGC récupérable, par taux.
tgc22 entier
Défaut : 0 Exemple : 2200
Montant de TGC à 22 %, en francs.
tgc11 entier
Défaut : 0
Montant de TGC à 11 %, en francs.
tgc6 entier
Défaut : 0
Montant de TGC à 6 %, en francs.
tgc3 entier
Défaut : 0
Montant de TGC à 3 %, en francs.
categoryId entier
Défaut : catégorie par défaut
Catégorie de dépense.
supplierId entier
Fournisseur, si le module Fournisseurs est actif.
clientId entier
Client concerné.
paymentStatus texte
Valeurs : paid · pending Défaut : paid
pending : dépense à payer, avec dueDate.
paymentMethod texte
Max : 255 caractères Exemple : Carte bancaire
paymentDate date
Format : AAAA-MM-JJ Défaut : date de la dépense
Si payée.
dueDate date
Format : AAAA-MM-JJ
Échéance, si à payer.
notes texte
Réponse 201
JSON
{
    "id": 55,
    "amount": 12200,
    "tva": {
        "tgc22": 2200
    },
    "title": "Fournitures de bureau",
    "supplierId": null,
    "supplierName": null,
    "categoryId": 3,
    "clientId": null,
    "date": "2026-09-20",
    "paymentStatus": "paid",
    "paymentMethod": "Carte bancaire",
    "paymentDate": "2026-09-20",
    "dueDate": null,
    "notes": null,
    "attachmentId": null,
    "attachmentUrl": null,
    "attachmentType": null,
    "attachmentName": null,
    "createdAt": "2026-09-20T10:02:11+11:00"
}
Produits 4
GET /products Lister les produits

Le catalogue, par ordre alphabétique (200 au plus) : de quoi remplir des lignes de devis ou de facture.

q texte
Exemple : miel
Recherche dans la désignation.
Réponse 200
JSON
{
    "data": [
        {
            "id": 12,
            "name": "Miel de Nouvelle-Calédonie 500 g",
            "unitPrice": 1500,
            "unitPriceExact": 1500,
            "tvaBucket": "tgc3",
            "unit": "pot",
            "kind": "produit"
        }
    ]
}
POST /products Créer un produit
name requis texte
Max : 255 caractères Exemple : Miel de Nouvelle-Calédonie 500 g
Désignation.
unitPrice requis nombre
Min : 0 Max : 99999999.99 Exemple : 1500
Prix unitaire HT.
tvaBucket texte
Valeurs : tgc22 · tgc11 · tgc6 · tgc3 · tgc0 Défaut : tgc11 Exemple : tgc3
Taux de TGC du produit.
unit texte
Max : 50 caractères Défaut : / Exemple : pot
kind texte
Valeurs : produit · service Défaut : produit
Nature du produit : livraison de biens ou prestation de services.
La référence (SKU), le stock, les descriptions et les images se gèrent dans le logiciel.
Réponse 201
JSON
{
    "id": 12,
    "name": "Miel de Nouvelle-Calédonie 500 g",
    "unitPrice": 1500,
    "unitPriceExact": 1500,
    "tvaBucket": "tgc3",
    "unit": "pot",
    "kind": "produit"
}
PUT /products/{id} Modifier un produit

Seuls les champs envoyés changent. Cette route ne modifie pas le stock.

Paramètres
id requis entier
Exemple : 42
Identifiant du produit.
Corps JSON
name texte
Max : 255 caractères
unitPrice nombre
Min : 0 Max : 99999999.99 Exemple : 1600
Prix unitaire HT.
tvaBucket texte
Valeurs : tgc22 · tgc11 · tgc6 · tgc3 · tgc0
Taux de TGC du produit.
unit texte
Max : 50 caractères
kind texte
Valeurs : produit · service
À savoir
404 : Produit introuvable.
422 : Aucun champ à modifier.
Réponse 200
JSON
{
    "id": 12,
    "name": "Miel de Nouvelle-Calédonie 500 g",
    "unitPrice": 1500,
    "unitPriceExact": 1500,
    "tvaBucket": "tgc3",
    "unit": "pot",
    "kind": "produit"
}
DELETE /products/{id} Supprimer un produit

Supprime le produit et ses images. Les factures déjà émises gardent leurs lignes.

id requis entier
Exemple : 42
Identifiant du produit.
404 : Produit introuvable.
Réponse 200
JSON
{
    "ok": true
}
Boutique en ligne 5
GET /shop/products Lire le catalogue et le stock

Les produits du catalogue avec leur prix, leur stock, leur catégorie, leurs descriptions et leurs images. Une synchronisation régulière ne demande que les produits modifiés depuis la précédente.

updatedSince date et heure
Format : ISO 8601 Exemple : 2026-09-23T08:00:00+11:00
Seulement les produits modifiés depuis cette date (stock et images compris).
sku texte
Max : 100 caractères Exemple : MIEL-500
Un seul produit, par sa référence.
hasSku entier
Valeurs : 0 · 1 Exemple : 1
1 : seulement les produits qui ont une référence, c'est-à-dire ceux vendus en ligne.
page entier
Min : 1 Défaut : 1
Numéro de page.
perPage entier
Min : 1 Max : 200 Défaut : 100
Éléments par page.
À savoir
stock et lowStockAlert valent null si le stock n'est pas suivi. Le stock est en unités entières. priceTtc est arrondi à la précision du compte (franc, ou centime pour un compte à 2 décimales).
Correspondance WooCommerce : priceTtc → regular_price, shortDescription → short_description, category.name → categories, images[].url → images[].src, stock → stock_quantity. Les URL d'images sont publiques.
Comparez régulièrement avec le catalogue complet pour détecter les produits retirés.
403 : Module boutique non activé sur ce compte (module_disabled).
Réponse 200
JSON
{
    "data": [
        {
            "id": 12,
            "sku": "MIEL-500",
            "name": "Miel de Nouvelle-Calédonie 500 g",
            "unit": "pot",
            "category": {
                "id": 14,
                "name": "Épicerie fine"
            },
            "shortDescription": "Miel de fleurs récolté à La Foa.",
            "description": "<p>Miel cru, non chauffé, mis en pot à la main.</p>",
            "images": [
                {
                    "id": 301,
                    "url": "https://VOTRE-COMPTE.caledocompta.com/…/miel-500.jpg",
                    "thumbnailUrl": "https://VOTRE-COMPTE.caledocompta.com/…/miel-500-thumb.jpg",
                    "name": "miel-500.jpg",
                    "position": 0
                }
            ],
            "priceHt": 1500,
            "tvaRate": 3,
            "priceTtc": 1545,
            "stockManaged": true,
            "stock": 42,
            "lowStockAlert": 5,
            "updatedAt": "2026-09-23T09:14:02+11:00"
        }
    ],
    "page": 1,
    "perPage": 100,
    "total": 1
}
POST /shop/orders Facturer une commande de la boutique

Retrouve ou crée le client (par email), crée la facture au prix payé et, si la commande est payée, le paiement. Le stock est décrémenté.

reference requis texte
Max : 100 caractères Caractères : A-Z a-z 0-9 . _ - Exemple : 1042
Numéro de la commande dans la boutique. Renvoyer une commande déjà reçue ne crée rien de plus.
source texte
Max : 50 caractères Défaut : woocommerce
Boutique d'origine. Avec reference, identifie la commande.
date date
Format : AAAA-MM-JJ Défaut : aujourd'hui
Date de la facture. Un horodatage UTC est ramené au jour de Nouméa. Échéance : le même jour si la commande est payée, sinon cette date + le délai de paiement des réglages (30 jours s'il est nul).
customer requis objet
L'acheteur. Un client existant avec le même email est réutilisé, sinon il est créé.
email requis email
Max : 255 caractères Exemple : client@example.com
company texte
Max : 255 caractères
Nom du client. À défaut : prénom et nom, puis l'email.
firstName texte
Max : 100 caractères Exemple : Teva
Prénom du contact.
lastName texte
Max : 100 caractères Exemple : Exemple
Nom du contact.
phone texte
Max : 40 caractères Exemple : +687 00 00 00
address objet
Adresse de facturation.
street texte
Max : 255 caractères Exemple : Rue du Commerce
city texte
Max : 100 caractères Exemple : Nouméa
zip texte
Max : 20 caractères Exemple : 98800
country texte
Max : 100 caractères
lines requis liste d'objets
Min : 1 élément
Les articles commandés, dans l'ordre de la facture.
sku requis texte
Max : 100 caractères Exemple : MIEL-500
Référence du produit dans CaledoCompta, majuscules indifférentes. Une référence inconnue refuse toute la commande.
quantity requis nombre
Min : 0.01 Max : 100000 Exemple : 2
Nombre entier si le stock du produit est suivi.
unitPriceTtc requis nombre
Min : 0 Max : 99999999 Exemple : 1545
Prix unitaire TTC réellement payé, coupons déduits. Le HT est recalculé avec le taux de TGC du produit.
name texte
Max : 500 caractères Défaut : la désignation du produit
Libellé de la ligne sur la facture.
shipping objet
Frais de livraison, ajoutés en dernière ligne de la facture.
amountTtc requis avec shipping nombre
Min : 0 Max : 99999999 Exemple : 1000
Montant TTC payé.
tvaRate requis si montant > 0 entier
Valeurs : 0 · 3 · 6 · 11 · 22 Exemple : 11
Taux de TGC des frais, en %.
label texte
Max : 255 caractères Défaut : Frais de livraison Exemple : Livraison Nouméa
payment requis objet
status requis texte
Valeurs : paid · pending Exemple : paid
paid : la facture est soldée. pending : elle reste due, à payer plus tard avec POST /shop/orders/{reference}/payment.
method texte
Max : 60 caractères Défaut : Boutique en ligne Exemple : Carte bancaire
Moyen de paiement affiché sur le paiement.
transactionId texte
Max : 100 caractères
Identifiant du paiement chez le prestataire, affiché sur le paiement.
date date
Format : AAAA-MM-JJ Défaut : aujourd'hui
totalTtc nombre
Min : 0 Exemple : 4090
Total payé sur la boutique. Il est comparé au total de la facture dans totals.
notes texte
Max : 2000 caractères
Note ajoutée à la facture.
À savoir
Stock : chaque réponse (réception, paiement, annulation) renvoie stock, le stock à jour des produits de la commande dont le stock est suivi. Reportez-le dans la boutique, qui décrémente aussi son propre stock.
Une commande déjà reçue renvoie 200 et "duplicate": true : un envoi peut être rejoué sans risque.
paymentRecorded indique si le paiement a été enregistré. S'il vaut false, enregistrez-le avec POST /shop/orders/{reference}/payment.
403 : Module boutique non activé sur ce compte (module_disabled).
422 : Référence de produit inconnue, quantité non entière pour un produit dont le stock est suivi, total nul ou taux de TGC des frais manquant : rien n'est créé.
409 : Opération impossible dans l'état actuel de la commande : réessayez plus tard ou consultez GET /shop/orders/{reference}.
Réponse 201
JSON
{
    "source": "woocommerce",
    "reference": "1042",
    "status": "invoiced",
    "clientId": 57,
    "invoice": {
        "id": 318,
        "number": "FACT-318",
        "clientId": 57,
        "clientName": "Teva Exemple",
        "title": "Commande en ligne n° 1042",
        "status": "paid",
        "subtotal": 3901,
        "discount": {
            "type": null,
            "percentage": 0,
            "amount": 0
        },
        "tvaTotal": 189,
        "total": 4090,
        "createdAt": "2026-09-23T09:20:11+11:00",
        "date": "2026-09-23",
        "dueDate": "2026-09-23",
        "lines": []
    },
    "creditNote": null,
    "totals": {
        "invoice": 4090,
        "site": 4090,
        "difference": 0
    },
    "stock": [
        {
            "sku": "MIEL-500",
            "stock": 40
        }
    ],
    "paymentRecorded": true
}
Réponse 200 : Commande déjà reçue : rien n'est recréé.
JSON
{
    "source": "woocommerce",
    "reference": "1042",
    "status": "invoiced",
    "clientId": 57,
    "invoice": {
        "id": 318,
        "number": "FACT-318",
        "clientId": 57,
        "clientName": "Teva Exemple",
        "title": "Commande en ligne n° 1042",
        "status": "paid",
        "subtotal": 3901,
        "discount": {
            "type": null,
            "percentage": 0,
            "amount": 0
        },
        "tvaTotal": 189,
        "total": 4090,
        "createdAt": "2026-09-23T09:20:11+11:00",
        "date": "2026-09-23",
        "dueDate": "2026-09-23",
        "lines": []
    },
    "creditNote": null,
    "totals": {
        "invoice": 4090,
        "site": 4090,
        "difference": 0
    },
    "stock": [
        {
            "sku": "MIEL-500",
            "stock": 40
        }
    ],
    "duplicate": true
}
GET /shop/orders/{reference} État d'une commande facturée

La commande, sa facture et, si elle a été annulée, son avoir.

reference requis texte
Max : 100 caractères Caractères : A-Z a-z 0-9 . _ - Exemple : 1042
Numéro de la commande dans la boutique.
source texte
Max : 50 caractères Défaut : woocommerce
Boutique d'origine, si la commande a été envoyée avec une autre source.
À savoir
404 : Aucune commande avec cette référence (et cette source).
403 : Module boutique non activé sur ce compte (module_disabled).
Réponse 200
JSON
{
    "source": "woocommerce",
    "reference": "1042",
    "status": "invoiced",
    "clientId": 57,
    "invoice": {
        "id": 318,
        "number": "FACT-318",
        "clientId": 57,
        "clientName": "Teva Exemple",
        "title": "Commande en ligne n° 1042",
        "status": "paid",
        "subtotal": 3901,
        "discount": {
            "type": null,
            "percentage": 0,
            "amount": 0
        },
        "tvaTotal": 189,
        "total": 4090,
        "createdAt": "2026-09-23T09:20:11+11:00",
        "date": "2026-09-23",
        "dueDate": "2026-09-23",
        "lines": []
    },
    "creditNote": null,
    "totals": {
        "invoice": 4090,
        "site": 4090,
        "difference": 0
    }
}
POST /shop/orders/{reference}/cancel Annuler une commande

Annulation totale : crée un avoir et remet le stock. Le remboursement se fait dans votre moyen de paiement. Une commande déjà annulée renvoie la même réponse, sans second avoir.

reference requis texte
Max : 100 caractères Caractères : A-Z a-z 0-9 . _ - Exemple : 1042
Numéro de la commande dans la boutique.
source texte
Max : 50 caractères Défaut : woocommerce
Boutique d'origine, si la commande a été envoyée avec une autre source.
À savoir
404 : Aucune commande avec cette référence (et cette source).
403 : Module boutique non activé sur ce compte (module_disabled).
409 : Opération impossible dans l'état actuel de la commande : réessayez plus tard ou consultez GET /shop/orders/{reference}.
Réponse 200
JSON
{
    "source": "woocommerce",
    "reference": "1042",
    "status": "cancelled",
    "clientId": 57,
    "invoice": {
        "id": 318,
        "number": "FACT-318",
        "clientId": 57,
        "clientName": "Teva Exemple",
        "title": "Commande en ligne n° 1042",
        "status": "paid",
        "subtotal": 3901,
        "discount": {
            "type": null,
            "percentage": 0,
            "amount": 0
        },
        "tvaTotal": 189,
        "total": 4090,
        "createdAt": "2026-09-23T09:20:11+11:00",
        "date": "2026-09-23",
        "dueDate": "2026-09-23",
        "lines": []
    },
    "creditNote": {
        "id": 325,
        "number": "FACT-325",
        "clientId": 57,
        "clientName": "Teva Exemple",
        "title": "Commande en ligne n° 1042",
        "status": "credit",
        "subtotal": -3901,
        "discount": {
            "type": null,
            "percentage": 0,
            "amount": 0
        },
        "tvaTotal": -189,
        "total": -4090,
        "createdAt": "2026-09-24T08:02:40+11:00",
        "date": "2026-09-24",
        "dueDate": "2026-09-24",
        "lines": []
    },
    "totals": {
        "invoice": 4090,
        "site": 4090,
        "difference": 0
    },
    "stock": [
        {
            "sku": "MIEL-500",
            "stock": 42
        }
    ]
}
POST /shop/orders/{reference}/payment Enregistrer le paiement d'une commande

Pour une commande envoyée en pending puis payée sur la boutique : enregistre le paiement du reste dû. Une facture déjà soldée n'est pas payée deux fois.

Paramètres
reference requis texte
Max : 100 caractères Caractères : A-Z a-z 0-9 . _ - Exemple : 1042
Numéro de la commande dans la boutique.
source texte
Max : 50 caractères Défaut : woocommerce
Boutique d'origine, si la commande a été envoyée avec une autre source.
Corps JSON
method texte
Max : 60 caractères Défaut : Boutique en ligne Exemple : Carte bancaire
transactionId texte
Max : 100 caractères Exemple : pi_3Q...
date date
Format : AAAA-MM-JJ Défaut : aujourd'hui
À savoir
404 : Aucune commande avec cette référence (et cette source).
403 : Module boutique non activé sur ce compte (module_disabled).
409 : Opération impossible dans l'état actuel de la commande : réessayez plus tard ou consultez GET /shop/orders/{reference}.
Réponse 200
JSON
{
    "source": "woocommerce",
    "reference": "1042",
    "status": "invoiced",
    "clientId": 57,
    "invoice": {
        "id": 318,
        "number": "FACT-318",
        "clientId": 57,
        "clientName": "Teva Exemple",
        "title": "Commande en ligne n° 1042",
        "status": "paid",
        "subtotal": 3901,
        "discount": {
            "type": null,
            "percentage": 0,
            "amount": 0
        },
        "tvaTotal": 189,
        "total": 4090,
        "createdAt": "2026-09-23T09:20:11+11:00",
        "date": "2026-09-23",
        "dueDate": "2026-09-23",
        "lines": []
    },
    "creditNote": null,
    "totals": {
        "invoice": 4090,
        "site": 4090,
        "difference": 0
    },
    "stock": [
        {
            "sku": "MIEL-500",
            "stock": 40
        }
    ],
    "paymentRecorded": true
}

5 Conventions

SujetRègle
FormatJSON en entrée et en sortie. Dates AAAA-MM-JJ, dates et heures en ISO 8601 avec fuseau.
ListesÉléments dans data, avec page, perPage et total. Factures et paiements, comme le catalogue de la boutique, se parcourent page par page (page, perPage). Les autres listes renvoient 1 000 éléments au plus.
MontantsEn XPF. Devis et factures : prix HT par ligne. Taux dans tvaBucket : tgc22, tgc11, tgc6, tgc3, tgc0. Commandes de la boutique : prix TTC payés.
SynchronisationFactures et paiements portent updatedAt et acceptent updatedSince : ne relisez que ce qui a changé depuis votre dernier passage. Un paiement enregistré ou supprimé compte comme une modification de sa facture.
IdempotenceEntête facultatif Idempotency-Key sur la création d'une facture, d'un avoir ou d'un paiement. Un appel renvoyé avec la même clé dans les 24 h ne crée rien de plus : il reçoit la réponse d'origine, avec l'entête Idempotent-Replayed: true. Même clé pour une autre requête : 422. Requête d'origine encore en cours : 409, réessayez. Une clé : 1 à 191 caractères ASCII sans espace, un UUID par exemple.
CommandesIdentifiées par source + reference : renvoyer une commande ne crée pas de doublon.
Limite90 requêtes par minute. Au-delà : 429.
DroitsUne clé a les droits de l'utilisateur qui l'a créée. Pour restreindre une intégration, créez sa clé depuis un utilisateur dont le rôle est limité.
VersionsL'API /api/v1 évolue sans rupture : nouveaux champs, nouvelles routes, nouveaux paramètres facultatifs. Ignorez les champs que vous ne connaissez pas. Un changement incompatible passera par une nouvelle version, annoncée au moins 6 mois avant l'arrêt de la précédente.

Erreurs. Le corps de la réponse est { code, message, fields }.

StatutSignification
401Clé absente, invalide ou révoquée
402Abonnement inactif
403Permission insuffisante ou module non activé
404Ressource introuvable
409Opération impossible dans l'état actuel
422Données invalides, détail dans fields
429Trop de requêtes