Documentation API

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

URL de base : https://VOTRE-COMPTE.fenuacompta.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.fenuacompta.com/api/v1/me \
  -H "Authorization: Bearer VOTRE_CLE_API"
JavaScript
const BASE = "https://VOTRE-COMPTE.fenuacompta.com/api/v1";
const token = process.env.FENUACOMPTA_API_KEY; // "fenuacompta_key_..."

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

function fenuacompta(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 = fenuacompta("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 : +689 00 00 00 00
cURL
curl -X POST https://VOTRE-COMPTE.fenuacompta.com/api/v1/clients \
  -H "Authorization: Bearer VOTRE_CLE_API" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Acme Sarl", "email": "contact@example.com", "phone": "+689 00 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: "+689 00 00 00 00" })
}).then(r => r.json());
PHP
$client = fenuacompta("POST", "/clients", [
    "name"  => "Acme Sarl",
    "email" => "contact@example.com",
    "phone" => "+689 00 00 00 00",
]);
Réponse 201
{ "id": 42, "name": "Acme Sarl", "email": "contact@example.com", "phone": "+689 00 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 : tva16 · tva13 · tva5 · tva1 · tva0 Défaut : tva16 Exemple : tva16
Taux de TVA 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 TVA 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.fenuacompta.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": "tva16" }
    ],
    "expiryDate": "2026-10-30"
  }'
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: "tva16" }
    ],
    expiryDate: "2026-10-30"
  })
}).then(r => r.json());
PHP
$estimate = fenuacompta("POST", "/estimates", [
    "clientId"   => 42,
    "lines"      => [
        ["description" => "Prestation de conseil", "unitPrice" => 10000, "quantity" => 1, "tvaBucket" => "tva16"],
    ],
    "expiryDate" => "2026-10-30",
]);
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.fenuacompta.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": "tva16" }
    ],
    "dueDate": "2026-10-30"
  }'
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: "tva16" }
    ],
    dueDate: "2026-10-30"
  })
}).then(r => r.json());
PHP
$invoice = fenuacompta("POST", "/invoices", [
    "clientId" => 42,
    "lines"    => [
        ["description" => "Prestation de conseil", "unitPrice" => 10000, "quantity" => 1, "tvaBucket" => "tva16"],
    ],
    "dueDate"  => "2026-10-30",
]);

3 Boutique en ligne (WooCommerce)

La boutique lit le catalogue et le stock de FenuaCompta, 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-10: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.fenuacompta.com/api/v1/shop/products?hasSku=1&updatedSince=2026-09-23T08:00:00-10: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 = fenuacompta("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 Tahiti 500 g", "unit": "pot",
      "category": { "id": 14, "name": "Épicerie fine" },
      "shortDescription": "Miel de fleurs récolté à Taravao.",
      "description": "<p>Miel cru, non chauffé, mis en pot à la main.</p>",
      "images": [
        { "id": 301, "url": "https://VOTRE-COMPTE.fenuacompta.com/…/miel-500.jpg",
          "thumbnailUrl": "https://VOTRE-COMPTE.fenuacompta.com/…/miel-500-thumb.jpg", "name": "miel-500.jpg", "position": 0 }
      ],
      "priceHt": 1500, "tvaRate": 5, "priceTtc": 1575,
      "stockManaged": true, "stock": 42, "lowStockAlert": 5,
      "updatedAt": "2026-09-23T09:14:02-10: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 Tahiti. É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 : +689 00 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 : Papeete
zip texte
Max : 20 caractères Exemple : 98714
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 FenuaCompta, 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 : 1575
Prix unitaire TTC réellement payé, coupons déduits. Le HT est recalculé avec le taux de TVA 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 · 1 · 5 · 13 · 16 Exemple : 13
Taux de TVA des frais, en %.
label texte
Max : 255 caractères Défaut : Frais de livraison Exemple : Livraison Tahiti
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 : 4150
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 TVA 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.fenuacompta.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": "+689 00 00 00 00", "address": { "street": "Rue du Commerce", "city": "Papeete", "zip": "98714" } },
    "lines": [ { "sku": "MIEL-500", "quantity": 2, "unitPriceTtc": 1575 } ],
    "shipping": { "label": "Livraison Tahiti", "amountTtc": 1000, "tvaRate": 13 },
    "payment": { "status": "paid", "method": "Carte bancaire", "transactionId": "pi_3Q..." },
    "totalTtc": 4150
  }'
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: 13 }, // 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 = fenuacompta("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"   => 13, // 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": 4150, ... },
  "creditNote": null,
  "totals": { "invoice": 4150, "site": 4150, "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 : +689 00 00 00 00
Réponse 201
JSON
{
    "id": 42,
    "name": "Acme Sarl",
    "email": "contact@example.com",
    "phone": "+689 00 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": "+689 00 00 00 00",
    "website": null,
    "vat": null,
    "city": "Papeete",
    "zip": "98714",
    "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": "+689 00 00 00 00",
    "website": null,
    "vat": null,
    "city": "Papeete",
    "zip": "98714",
    "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": 1600,
            "total": 11600,
            "createdAt": "2026-09-28T08:16:30-10: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 : tva16 · tva13 · tva5 · tva1 · tva0 Défaut : tva16 Exemple : tva16
Taux de TVA 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 TVA 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": 1600,
    "total": 11600,
    "createdAt": "2026-09-28T08:16:30-10: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": "tva16",
            "lineTotal": 10000
        }
    ],
    "tvaBreakdown": [
        {
            "key": "tva16",
            "label": "TVA 16 %",
            "rate": 16,
            "amount": 1600
        }
    ],
    "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 TVA 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": 1600,
    "total": 11600,
    "createdAt": "2026-09-28T08:16:30-10: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": "tva16",
            "lineTotal": 10000
        }
    ],
    "tvaBreakdown": [
        {
            "key": "tva16",
            "label": "TVA 16 %",
            "rate": 16,
            "amount": 1600
        }
    ],
    "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.fenuacompta.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 6
GET /invoices Lister les factures

Les factures, de la plus récente à la plus ancienne (1 000 au plus), avec le payé et le reste dû.

Statuts : draft, due, overdue, part_paid, paid, credit (avoir).
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": 1600,
            "total": 11600,
            "createdAt": "2026-09-28T08:16:30-10:00",
            "date": "2026-09-28",
            "dueDate": "2026-10-28",
            "lines": [],
            "paid": 0,
            "balance": 11600
        }
    ]
}
POST /invoices Créer une facture
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 : tva16 · tva13 · tva5 · tva1 · tva0 Défaut : tva16 Exemple : tva16
Taux de TVA 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 TVA 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": 1600,
    "total": 11600,
    "createdAt": "2026-09-28T08:16:30-10:00",
    "date": "2026-09-28",
    "dueDate": "2026-10-28",
    "lines": [
        {
            "id": 19,
            "productId": null,
            "description": "Prestation de conseil",
            "unitPrice": 10000,
            "unitPriceExact": 10000,
            "quantity": 1,
            "unit": "u",
            "tvaBucket": "tva16",
            "lineTotal": 10000
        }
    ],
    "tvaBreakdown": [
        {
            "key": "tva16",
            "label": "TVA 16 %",
            "rate": 16,
            "amount": 1600
        }
    ],
    "terms": "<p>Mauruuru pour votre confiance.</p>",
    "hasSections": false,
    "payments": [],
    "paid": 0,
    "balance": 11600,
    "emails": []
}
GET /invoices/{id} Détail d'une facture

La facture avec ses lignes, le détail de la TVA, 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": 1600,
    "total": 11600,
    "createdAt": "2026-09-28T08:16:30-10:00",
    "date": "2026-09-28",
    "dueDate": "2026-10-28",
    "lines": [
        {
            "id": 19,
            "productId": null,
            "description": "Prestation de conseil",
            "unitPrice": 10000,
            "unitPriceExact": 10000,
            "quantity": 1,
            "unit": "u",
            "tvaBucket": "tva16",
            "lineTotal": 10000
        }
    ],
    "tvaBreakdown": [
        {
            "key": "tva16",
            "label": "TVA 16 %",
            "rate": 16,
            "amount": 1600
        }
    ],
    "terms": "<p>Mauruuru pour votre confiance.</p>",
    "hasSections": false,
    "payments": [],
    "paid": 0,
    "balance": 11600,
    "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.fenuacompta.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"
}
Paiements & dépenses 3
POST /payments Enregistrer un paiement

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

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": 11600,
            "tva": {
                "tva16": 1600
            },
            "importTva": null,
            "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-10: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
TVA récupérable, par taux.
tva16 entier
Défaut : 0 Exemple : 1600
Montant de TVA à 16 %, en francs.
tva13 entier
Défaut : 0
Montant de TVA à 13 %, en francs.
tva5 entier
Défaut : 0
Montant de TVA à 5 %, en francs.
tva1 entier
Défaut : 0
Montant de TVA à 1 %, en francs.
importTva entier
TVA payée à l'importation, 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": 11600,
    "tva": {
        "tva16": 1600
    },
    "importTva": null,
    "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-10: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 Tahiti 500 g",
            "unitPrice": 1500,
            "unitPriceExact": 1500,
            "tvaBucket": "tva5",
            "unit": "pot",
            "kind": "produit"
        }
    ]
}
POST /products Créer un produit
name requis texte
Max : 255 caractères Exemple : Miel de Tahiti 500 g
Désignation.
unitPrice requis nombre
Min : 0 Max : 99999999.99 Exemple : 1500
Prix unitaire HT.
tvaBucket texte
Valeurs : tva16 · tva13 · tva5 · tva1 · tva0 Défaut : tva16 Exemple : tva5
Taux de TVA du produit.
unit texte
Max : 50 caractères Défaut : / Exemple : pot
kind texte
Valeurs : produit · service Défaut : produit
Sert à ventiler la TVA (livraisons de biens ou prestations 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 Tahiti 500 g",
    "unitPrice": 1500,
    "unitPriceExact": 1500,
    "tvaBucket": "tva5",
    "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 : tva16 · tva13 · tva5 · tva1 · tva0
Taux de TVA 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 Tahiti 500 g",
    "unitPrice": 1500,
    "unitPriceExact": 1500,
    "tvaBucket": "tva5",
    "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-10: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 Tahiti 500 g",
            "unit": "pot",
            "category": {
                "id": 14,
                "name": "Épicerie fine"
            },
            "shortDescription": "Miel de fleurs récolté à Taravao.",
            "description": "<p>Miel cru, non chauffé, mis en pot à la main.</p>",
            "images": [
                {
                    "id": 301,
                    "url": "https://VOTRE-COMPTE.fenuacompta.com/…/miel-500.jpg",
                    "thumbnailUrl": "https://VOTRE-COMPTE.fenuacompta.com/…/miel-500-thumb.jpg",
                    "name": "miel-500.jpg",
                    "position": 0
                }
            ],
            "priceHt": 1500,
            "tvaRate": 5,
            "priceTtc": 1575,
            "stockManaged": true,
            "stock": 42,
            "lowStockAlert": 5,
            "updatedAt": "2026-09-23T09:14:02-10: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 Tahiti. É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 : +689 00 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 : Papeete
zip texte
Max : 20 caractères Exemple : 98714
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 FenuaCompta, 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 : 1575
Prix unitaire TTC réellement payé, coupons déduits. Le HT est recalculé avec le taux de TVA 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 · 1 · 5 · 13 · 16 Exemple : 13
Taux de TVA des frais, en %.
label texte
Max : 255 caractères Défaut : Frais de livraison Exemple : Livraison Tahiti
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 : 4150
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 TVA 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": 3634,
        "discount": {
            "type": null,
            "percentage": 0,
            "amount": 0
        },
        "tvaTotal": 516,
        "total": 4150,
        "createdAt": "2026-09-23T09:20:11-10:00",
        "date": "2026-09-23",
        "dueDate": "2026-09-23",
        "lines": []
    },
    "creditNote": null,
    "totals": {
        "invoice": 4150,
        "site": 4150,
        "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": 3634,
        "discount": {
            "type": null,
            "percentage": 0,
            "amount": 0
        },
        "tvaTotal": 516,
        "total": 4150,
        "createdAt": "2026-09-23T09:20:11-10:00",
        "date": "2026-09-23",
        "dueDate": "2026-09-23",
        "lines": []
    },
    "creditNote": null,
    "totals": {
        "invoice": 4150,
        "site": 4150,
        "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": 3634,
        "discount": {
            "type": null,
            "percentage": 0,
            "amount": 0
        },
        "tvaTotal": 516,
        "total": 4150,
        "createdAt": "2026-09-23T09:20:11-10:00",
        "date": "2026-09-23",
        "dueDate": "2026-09-23",
        "lines": []
    },
    "creditNote": null,
    "totals": {
        "invoice": 4150,
        "site": 4150,
        "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": 3634,
        "discount": {
            "type": null,
            "percentage": 0,
            "amount": 0
        },
        "tvaTotal": 516,
        "total": 4150,
        "createdAt": "2026-09-23T09:20:11-10: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": -3634,
        "discount": {
            "type": null,
            "percentage": 0,
            "amount": 0
        },
        "tvaTotal": -516,
        "total": -4150,
        "createdAt": "2026-09-24T08:02:40-10:00",
        "date": "2026-09-24",
        "dueDate": "2026-09-24",
        "lines": []
    },
    "totals": {
        "invoice": 4150,
        "site": 4150,
        "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": 3634,
        "discount": {
            "type": null,
            "percentage": 0,
            "amount": 0
        },
        "tvaTotal": 516,
        "total": 4150,
        "createdAt": "2026-09-23T09:20:11-10:00",
        "date": "2026-09-23",
        "dueDate": "2026-09-23",
        "lines": []
    },
    "creditNote": null,
    "totals": {
        "invoice": 4150,
        "site": 4150,
        "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. Les listes renvoient leurs éléments dans data, sans pagination (sauf le catalogue de la boutique) : 1 000 au plus, 200 pour les produits.
MontantsEn XPF. Devis et factures : prix HT par ligne. Taux dans tvaBucket : tva16, tva13, tva5, tva1, tva0. Commandes de la boutique : prix TTC payés.
CommandesIdentifiées par source + reference : renvoyer une commande ne crée pas de doublon.
Limite90 requêtes par minute. Au-delà : 429.

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