Factures
Le cycle de vie complet d’une facture depuis votre système : brouillon, émission, envoi, encaissement et annulation.
Vue d’ensemble
Une facture naît à l’état de brouillon et ne devient définitive que lorsque vous l’émettez. L’émission est une action explicite et irréversible : elle consomme le timbrage de votre offre lorsqu’il s’applique (CFDI au Mexique) et attribue son numéro à la facture. La création n’émet jamais d’elle-même.
L’API des factures est disponible dans toutes les offres, y compris l’offre Gratuite, avec des factures non transmises (pro forma au Mexique et en Espagne). L’émission fiscale intégrée (CFDI au Mexique, et Verifactu en Espagne avec le certificat de l’entreprise chargé) exige l’offre Starter ou supérieure : demander document_mode: "fiscal" sans cette offre répond 400 invalid_request.
Lister les factures
GET /api/v1/facturas avec ces filtres facultatifs :
| Paramètre | Effet |
|---|---|
estado |
draft, open, paid, void, uncollectible ou overdue (ouvertes dont l’échéance est déjà passée). |
cliente |
Id du client. |
desde, hasta |
Plage par date de création, YYYY-MM-DD, bornes incluses. |
q |
Recherche par numéro, folio fiscal, numéro du devis d’origine ou nom du client. |
limit |
De 1 à 200 ; 50 par défaut. |
cursor |
Le next_cursor de la page précédente. |
La pagination se fait par curseur, et non par décalage : une nouvelle facture ne déplace jamais la page que vous lisez.
curl "https://cordhq.app/api/v1/facturas?limit=20" \
-H "Authorization: Bearer sk_live_tU..."
{
"data": [
{
"id": "f3a1c7e9-2b4d-4f6a-8c0e-5d7b9a1c3e24", "numero": "F-0231", "folio_fiscal": "6F1C2A9E-7B4D-4E6A-8C2F-1D5B9E3A7C40", "cliente": "Aceros del Norte",
"estado": "open", "estado_fiscal": "issued", "pais": "MX", "tipo": "cfdi_40",
"moneda": "MXN", "total": 184300, "pagado": 0, "saldo": 184300,
"vence": "2026-10-15", "vencida": false, "cotizacion_id": "2a9d8e4f-6b1c-4d7a-9e3f-5c8b1a2d4e6f", "creada": "15 sep 2026", "language": "es"
}
],
"meta": { "next_cursor": null }
}
creada arrive sous forme de date d’affichage (15 sep 2026), et non de date ISO ; vence, en revanche, est au format YYYY-MM-DD.
| Champ | Valeurs |
|---|---|
estado |
draft (brouillon), open (émise et à encaisser), paid (payée), void (annulée) ou uncollectible (irrécouvrable). |
estado_fiscal |
pending, issued (enregistrée auprès du fournisseur fiscal), cancelled ou error. |
tipo |
cfdi_40 (CFDI de revenu, Mexique), cfdi_egreso (avoir CFDI), proforma (document commercial au Mexique, en Espagne et dans les pays à facture autorisée), commercial_invoice (facture commerciale), commercial_credit_note (avoir commercial), verifactu_invoice ou verifactu_credit_note (Espagne avec Verifactu). Lorsque l’émission auprès de l’autorité est active : arca_invoice (Argentine), nfse_invoice et nfe_invoice (Brésil), sii_invoice (Chili), dian_invoice (Colombie) et sunat_invoice (Pérou), avec leurs avoirs *_credit_note et, au Chili, sii_debit_note. |
language |
Lecture seule. La langue dans laquelle le client reçoit la facture, son PDF, son lien et ses e-mails : es, en, pt, fr ou de. La facture la prend à l’émission, du client ou, s’il n’en a pas, de votre organisation ; un avoir hérite de celle de sa facture. null pour un brouillon. |
Créer un brouillon
POST /api/v1/facturas crée un brouillon. Nécessite une clé avec le droit d’écriture et accepte Idempotency-Key.
| Champ | Obligatoire | Détail |
|---|---|---|
cliente_id |
Oui | Un client de votre organisation. |
items |
Oui | De 1 à 200 lignes. Chacune avec descripcion et cantidad ; en option precio_unitario, precio_negociado, producto_id, costo_unitario, tax_rate, exemption_reason et, au Mexique, clave_sat et clave_unidad_sat. |
currency |
Non | Devise de la facture ; par défaut celle de votre compte. |
due_date |
Non | Échéance au format YYYY-MM-DD. |
notas |
Non | Jusqu’à 1000 caractères. |
iva_incluido |
Non | true si les prix incluent déjà la taxe. |
document_mode |
Non | commercial ou fiscal. Sans lui, Cord émet un document fiscal si votre offre l’inclut et si votre pays l’a activé, et un document commercial dans le cas contraire. fiscal sans l’offre ou sans pays activé répond 400 invalid_request. |
fx_buffer_pct |
Non | Marge de couverture en points de pourcentage sur le taux de change de référence lorsque currency diffère de votre devise comptable (2 = +2 %, plafond de 25). 0 par défaut. |
descuento |
Non | Remise sur le document avant taxes : { "tipo": "porcentaje", "valor": 10 } ou { "tipo": "monto", "valor": 2500 }. Cord calcule le montant et le répartit entre les lignes. Voir Remises et coupons. |
cupon |
Non | Le code d’un coupon de votre compte. Il l’emporte sur descuento. Son utilisation est décomptée à l’émission de la facture. |
service_date, service_date_end |
Non | Date ou période de prestation, YYYY-MM-DD. La fin exige le début et ne peut pas lui être antérieure. Sans elle, la facture indique qu’elle coïncide avec la date d’émission (obligatoire en Allemagne). |
buyer_reference |
Non | Référence de l’acheteur (BT-10 de la facture électronique européenne ; en Allemagne, le Leitweg-ID de l’administration publique). Sans elle, celle du client. Si l’adresse électronique du client est un Leitweg-ID, sa clé de contrôle est vérifiée et un identifiant qui ne passe pas répond 400. |
purchase_order |
Non | Numéro du bon de commande du client (BT-13). |
tax_rate est une fraction (0.16, et non 16) et elle est validée par rapport à votre catalogue de taxes : vous ne pouvez pas déclarer une ligne exonérée sur une vente taxable. 0 signifie exonérée volontairement ; l’omettre applique le taux de votre compte. clave_sat et clave_unidad_sat l’emportent sur les clés du produit ; en l’absence des deux, le CFDI utilise 01010101 et H87. Une clé au format non valide répond 400.
curl -X POST "https://cordhq.app/api/v1/facturas" \
-H "Authorization: Bearer sk_live_tU..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: invoice-order-8812" \
-d '{
"cliente_id": "9b2e4c6a-8d1f-4a3b-b5c7-0e2d4f6a8c91",
"currency": "USD",
"due_date": "2026-10-15",
"items": [{ "descripcion": "Rebar 3/8\"", "cantidad": 120, "precio_unitario": 4.2, "tax_rate": 0.0825 }]
}'
{ "data": { "id": "f3a1c7e9-2b4d-4f6a-8c0e-5d7b9a1c3e24" } }
Si la facture est dans une devise autre que votre devise comptable et qu’aucun taux de change vérifiable ne peut être obtenu, elle répond 503 avec code: "fx_unavailable" : réessayez plus tard, Cord n’invente jamais un taux.
Consulter une facture
GET /api/v1/facturas/{id} renvoie les champs de la liste ainsi que subtotal, impuestos, moneda_contable, tipo_cambio, total_contable, notas, nota_credito_de, emisor, receptor, descuento, conceptos et pagos.
| Champ | Détail |
|---|---|
descuento |
null, ou { tipo, valor, cupon, monto, moneda } : la définition, le coupon dont elle provient et le montant avant taxes. subtotal est déjà net. |
conceptos[].precio_unitario |
Prix unitaire net, après la remise sur le document, hors taxe. |
conceptos[].subtotal |
Base nette de la ligne. |
conceptos[].descuento |
La part de la remise sur le document attribuée à cette ligne ; 0 s’il n’y en a pas. |
conceptos[].clave_sat, conceptos[].clave_unidad_sat |
Mexique : les clés du SAT avec lesquelles la ligne a été timbrée ; null hors du Mexique. |
pagos |
Chaque paiement avec monto, moneda, metodo, referencia et cuando. Un paiement qui a réglé plusieurs factures apparaît sur chacune avec sa part. |
Changer le statut
POST /api/v1/facturas/{id} avec action :
action |
Effet | Champs |
|---|---|---|
finalize |
Émet la facture. Irréversible ; timbre le CFDI au Mexique lorsque cela s’applique. | — |
send |
Envoie par e-mail la facture et son PDF au client, dans la langue de la facture (language). Exige une facture émise et un client doté d’une adresse e-mail. |
— |
payment |
Enregistre un paiement, total ou partiel. | monto, moneda, metodo (par défaut manual), referencia |
void |
Annule la facture. | motivo |
credit_note |
Émet un avoir sur la facture. | monto (facultatif ; sans lui, pour le total), motivo |
payment répond avec le montant payé, le solde et le statut qui en résulte. Un paiement qui solde la facture déclenche l’événement invoice.paid.
Si une facture déjà timbrée ne peut pas être annulée directement, void répond 409 avec code: "credit_note_required" : émettez plutôt un avoir.
Au Mexique :
voiddemande l’annulation du CFDI avec le motif 02 du SAT. Si le SAT ne l’a pas encore confirmée, il répond202avec{ "data": { "id": "…", "estado": "open", "cancelacion": "pendiente" } }et la facture reste valide ;invoice.voidedn’est déclenché qu’une fois l’annulation confirmée. La substitution avec le motif 01 et la facture globale ne sont disponibles que dans l’application.paymentsur un CFDI PPD déclenche le complément de paiement automatique de ce paiement.
Erreurs fréquentes
| Code | Quand |
|---|---|
invalid_request (400) |
cliente_id ou items est manquant, une ligne n’a pas de description ou de quantité, due_date n’est pas au format YYYY-MM-DD, la remise n’a pas la forme { tipo, valor } ou un Leitweg-ID ne passe pas sa clé de contrôle. |
coupon_no_existe (404) |
Le coupon n’existe pas dans votre compte. |
coupon_inactivo, coupon_vencido, coupon_aun_no_vigente, coupon_agotado, coupon_agotado_cliente, coupon_moneda, coupon_requiere_cliente (409) |
Le coupon ne s’applique pas à cette facture ; le message indique pourquoi. |
invalid_state (409) |
L’action ne s’applique pas au statut actuel (par exemple, envoyer un brouillon). Envoyer à un client sans adresse e-mail répond 400 avec ce même code. |
credit_note_required (409) |
La facture déjà timbrée ne peut pas être annulée directement : émettez un avoir. |
not_found (404) |
La facture n’existe pas dans votre organisation. |
provider_error (502) |
Le fournisseur fiscal a rejeté l’émission ; le message indique pourquoi. |
send_failed (502) |
L’e-mail de la facture n’a pas pu être envoyé. Relancez send. |
fx_unavailable, tax_catalog_unavailable (503) |
Aucun taux de change vérifiable, ou votre catalogue de taxes n’a pas pu être lu. Réessayez. |