Facturino / Documentation / Produits

Produits

L'objet product représente une prestation ou un bien réutilisable dans votre catalogue. Les produits ne sont pas obligatoires — vous pouvez créer des factures avec des lignes ad-hoc — mais ils accélèrent la saisie et garantissent la cohérence des libellés, prix et taux de TVA entre vos documents.

Endpoints

MéthodeCheminDescription
POST/v1/productsCréer un produit
GET/v1/productsLister les produits
GET/v1/products/:idRécupérer un produit
PATCH/v1/products/:idModifier un produit
DELETE/v1/products/:idSupprimer (soft-delete)

Créer un produit

$ curl -X POST https://facturino.com/api/v1/products \
  -H "Authorization: Bearer fac_test_..." \
  -H "Idempotency-Key: product-sku-734-create" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Audit cybersécurité — Forfait",
    "reference": "AUDIT-CYBER-1",
    "description": "Audit complet : analyse, recommandations, restitution.",
    "unitPrice": 350000,
    "vatRate": 2000,
    "vatCode": "S",
    "unit": "flat_rate",
    "category": "consulting",
    "tags": ["audit", "cyber"]
  }'

Champs

ChampTypeRequisDescription
namestringouiNom affiché (max 200 caractères).
referencestringnonRéférence interne / SKU (max 50 caractères) — utile pour rapprocher avec un PIM/ERP.
descriptionstringnonDescription longue pré-remplie sur les lignes (max 500 caractères).
unitPriceintegerouiPrix unitaire HT en centimes (15000 = 150,00 €).
vatRateintegerouiTaux TVA en centièmes de pourcent (2000 = 20 %).
vatCodeenumouiS, Z, E, AE, G, IC, K, O, VATEX-FR-FRANCHISE (cf. codes TVA EN 16931).
unitenumouiunit (pièce), hour, day, month, flat_rate (forfait), kg, m, m2, m3, l.
categorystringnonCatégorie libre (max 100 caractères) pour le regroupement et les rapports.
tagsstring[]nonÉtiquettes libres (max 20 tags, 50 caractères chacun) — exposées dans les filtres de liste.

Le champ active n'est pas modifiable à la création — un produit est créé actif par défaut. Pour l'archiver, utilisez DELETE /v1/products/:id (soft-delete : il reste référençable par les anciennes factures mais disparaît des sélecteurs UI).

Utiliser un produit dans une ligne

Fournissez les champs de la ligne (description, quantity, unit, unitPrice, vatRate, vatCode) et, si vous le souhaitez, le champ product pour lier la ligne au produit du catalogue. Il n'y a pas de copie automatique : pré-remplissez la ligne depuis GET /v1/products/{id} côté client.

# Ligne de facture avec référence produit optionnelle (champ "product")
# Les valeurs de la ligne sont fournies explicitement ; "product" est un simple
# lien (dépliable via ?expand=items.product sur la réponse), pas une copie auto.
{
  "customerId": "cus_...",
  "lines": [
    {
      "description": "Audit cybersécurité",
      "quantity": "2",
      "unit": "flat_rate",
      "unitPrice": 300000,
      "vatRate": 2000,
      "vatCode": "S",
      "product": "prod_a1b2c3"
    }
  ]
}

# "product" est facultatif : une ligne peut être entièrement libre
{
  "customerId": "cus_...",
  "lines": [
    {
      "description": "Prestation sur mesure",
      "quantity": "1",
      "unit": "flat_rate",
      "unitPrice": 150000,
      "vatRate": 2000,
      "vatCode": "S"
    }
  ]
}

Pourquoi fournir les valeurs ? Une facture finalisée est immuable (numéro opposable, hash chain). Chaque ligne embarque ses propres valeurs figées à la date d'émission : modifier le prix d'un produit dans le catalogue ne change donc pas les factures historiques. Le champ product reste un lien (dépliable via ?expand=items.product sur la réponse), pas une référence vivante.

Filtres supportés sur GET /v1/products :

ParamètreDescription
qRecherche par préfixe du name (insensible à la casse)
categoryFiltrer par catégorie (correspondance exacte)
activetrue, false, ou omis pour tout
limitNombre d'éléments par page (défaut 25, max 100)
date_from, date_toFiltrer par date de création (ISO 8601)
sortOrdre de tri (hérité de la pagination)

Création en lot

Pour importer un catalogue complet, utilisez POST /v1/products/import : envoyez le CSV en JSON dans un champ csv (corps application/json). L'export miroir GET /v1/products/export renvoie l'ensemble de vos produits au format CSV avec le même en-tête de colonnes.

Vous pouvez aussi scripter via boucle POST /v1/products avec un Idempotency-Key stable par référence pour permettre les retries :

for product in catalog:
    key = f"product-import-{product.reference}"
    client.products.create(
        name=product.name,
        reference=product.reference,
        unitPrice=product.price_cents,
        vatRate=product.vat_centi,
        vatCode="S",
        idempotency_key=key,
    )

Respectez la limite de débit de votre plan — espacez les appels si nécessaire ou utilisez l'auto-pagination intégrée aux SDKs.

Suppression

DELETE /v1/products/:id est un soft-delete (deleted: true). Les factures historiques référençant le produit ne sont pas affectées (snapshot). Le produit n'apparaît plus dans le catalogue, mais reste consultable via GET /v1/products?include_deleted=true pour le debug.

Étapes suivantes