Aller au contenu

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 :

  • void demande l’annulation du CFDI avec le motif 02 du SAT. Si le SAT ne l’a pas encore confirmée, il répond 202 avec { "data": { "id": "…", "estado": "open", "cancelacion": "pendiente" } } et la facture reste valide ; invoice.voided n’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.
  • payment sur 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.