API de génération de factures
Générez des factures PDF professionnelles par programme depuis votre serveur, pour vos systèmes internes, marketplaces ou produits SaaS.
1. Authentification#
Créez une API key sur app.invosend.com/settings/api-keys. Un workspace payant et un rôle owner sont requis.
Envoyez la clé comme Bearer token dans le header Authorization à chaque requête :
Authorization: Bearer isk_live_xxxxxxxxxxxxxxxxxxxxxxxx403. Elles sont aussi rejetées si le workspace est gratuit, suspendu ou expiré.2. Endpoint#
Base URL: https://app.invosend.com
Description de l'API lisible par machine : OpenAPI 3.1 et Postman collection. Importez l'une ou l'autre dans Postman, Insomnia ou un générateur de SDK.
3. Request Body#
Exemple complet de requête :
curl -X POST https://app.invosend.com/api/invoices/generate-external \
-H "Authorization: Bearer isk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"customer_name": "Acme Corp",
"customer_email": "billing@acme.com",
"items": [
{ "description": "Consulting Services", "quantity": 2, "price": 500, "tax_rate": 11 }
],
"discount_total": 50,
"currency": "EUR",
"notes": "Thank you for your business."
}'Exemple de facture récurrente (la première maintenant, puis une par mois, 6 au total) :
curl -X POST https://app.invosend.com/api/invoices/generate-external \
-H "Authorization: Bearer isk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"customer_name": "Acme Corp",
"customer_email": "billing@acme.com",
"items": [
{ "description": "Monthly retainer", "quantity": 1, "price": 2500 }
],
"currency": "EUR",
"recurring_interval": "monthly",
"recurring_count": 6
}'Idempotency-Key (1 à 255 caractères, par exemple un UUID généré pour chaque facture). Si la première requête a réussi, la nouvelle tentative renvoie la même réponse avec l'en-tête Idempotent-Replayed: true, sans créer une autre facture ni consommer un autre crédit (credits_remaining est la valeur du premier appel). Les clés sont conservées 24 heures par espace de travail. Seules les réponses réussies sont enregistrées : une requête en échec peut donc être réessayée avec la même clé.4. Réponse#
200 OK signifie que la facture a été créée et que le PDF a été généré :
{
"data": {
"id": "cjld2cjxh0000qzrmn831i7rn",
"invoice_number": "INV-1-202609-0016",
"pdf_url": "https://cdn.invosend.com/company/1/pdf/Invoice_INV_1_202609_0016_UNPAID_0da2beeabb.pdf",
"credits_remaining": 24,
"is_recurring": false,
"template": {
"id": "k3p9x2m7c0000abcd1234efgh",
"name": "Classic",
"source": "system_default"
}
}
}credits_remaining vaut null lorsque le workspace dispose d'un quota illimité. id sert à appeler les Endpoints supplémentaires ci-dessous. Les factures créées via l'API apparaissent aussi dans la liste du workspace et utilisent la même séquence de numéros. Les numéros de facture ressemblent à INV-{id du workspace}-{AAAAMM}-{séquence}. Pour une facture récurrente, la réponse contient aussi un objet recurring : schedule_id, interval, occurrences, next_issue_date, end_date. recurring.schedule_id est l'identifiant à utiliser avec les endpoints récurrents ci-dessous.5. Codes d'erreur#
6. Rate Limit#
X-RateLimit-Limit et X-RateLimit-Remaining. Les quotas d'API du workspace sont configurés par forfait d'abonnement dans Invosend. Besoin d'un volume de production plus élevé ? Contactez-nous depuis votre compte workspace. Les clés révoquées ne comptent pas dans la limite du nombre de clés.7. Endpoints supplémentaires#
La même API key peut aussi lire et gérer les factures qu'elle a créées via generate-external :
payment_gateway (et éventuellement payment_account) dans generate-external, puis envoyez à votre client la page de paiement publique de la facture : https://app.invosend.com/p/invoice/{id}, avec l'id renvoyé par l'API. Il y paie via la passerelle connectée et la facture est marquée comme payée automatiquement. Le paiement est géré par cette page ; il n'existe pas d'endpoint de paiement public distinct à appeler.8. Webhooks#
Plutôt que d'interroger l'API en boucle, enregistrez une URL HTTPS : Invosend y envoie une requête POST avec un corps JSON chaque fois qu'une facture change. Ajoutez des endpoints dans Paramètres > Webhooks (propriétaire de l'espace de travail, offre avec accès à l'API, jusqu'à 5 endpoints). Chaque endpoint possède son propre secret de signature, affiché une seule fois.
Les événements sont envoyés pour les factures créées dans le tableau de bord comme pour celles créées via cette API. Les modèles de séries récurrentes ne sont jamais envoyés.
Tous les événements ont la même enveloppe. data.object est la facture, avec la même forme que GET /api/invoices/external/:id ; les événements de statut incluent aussi data.previous_status :
{
"id": "evt_9f2c1b7a4e3d5c6b8a1f0e2d",
"object": "event",
"type": "invoice.paid",
"created": "2026-10-01T09:30:12.000Z",
"data": {
"object": {
"id": "cjld2cjxh0000qzrmn831i7rn",
"invoice_number": "INV-1-202610-0007",
"customer_name": "Acme Corp",
"customer_email": "billing@acme.com",
"currency": "USD",
"subtotal": 500,
"discount_total": 0,
"tax_rate": 0,
"tax_amount": 0,
"amount": 500,
"amount_paid": 500,
"amount_credited": 0,
"amount_received": 500,
"invoice_status": "paid",
"is_archived": false,
"is_recurring": false,
"recurring_interval": "none",
"issue_date": "2026-10-01T02:15:40.000Z",
"due_date": "2026-10-15",
"paid_at": "2026-10-01T09:30:11.000Z",
"pdf_url": "https://cdn.invosend.com/company/1/pdf/Invoice_INV_1_202610_0007_PAID.pdf",
"pdf_status": "ready"
},
"previous_status": "unpaid"
}
}Chaque requête porte ces en-têtes. Pour la vérifier, calculez un HMAC-SHA256 de {t}.{corps brut} avec le secret de l'endpoint et comparez-le à v1 ; rejetez-la si t date de plus de 5 minutes :
POST /your/webhook/url
Content-Type: application/json
Invosend-Event: invoice.paid
Invosend-Delivery: evt_9f2c1b7a4e3d5c6b8a1f0e2d
Invosend-Signature: t=1790847012,v1=5b1d...e9a2
// Node.js
import crypto from "crypto";
function verify(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(parts.t + "." + rawBody)
.digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}2xx en moins de 10 secondes. Sinon, l'envoi est retenté jusqu'à 7 fois (après 1 minute, 5 minutes, 30 minutes, 2 heures, 6 heures, 12 heures et 24 heures). Un endpoint qui échoue en continu est désactivé et vous êtes notifié. Un événement peut arriver plusieurs fois ou dans le désordre : utilisez l'id de l'événement pour ignorer les doublons et considérez invoice_status comme la référence. Les journaux de livraison sont conservés 30 jours et tout événement peut être renvoyé depuis Paramètres > Webhooks.9. Limitations#
Cette API est volontairement limitée à la génération de factures et à une gestion légère. Ce qui n'est pas encore disponible :
- Les webhooks couvrent uniquement la création, le paiement, le retard et l'annulation d'une facture. Les autres changements, comme les modifications ou l'archivage, ne sont pas envoyés : lisez l'état actuel avec
GET /invoices/external/:id. - La facture créée par chaque requête n'est pas envoyée par e-mail : cette API ne fait que générer le PDF, la transmettre à votre client vous incombe (ou utilisez le tableau de bord). Exception : les séries récurrentes, où chaque facture suivante générée par le planificateur est envoyée automatiquement à
customer_email. - Une facture ne peut pas être modifiée après sa création — seuls son statut et son statut d'archivage peuvent être changés via cette API.
- La prise en charge d'une passerelle de paiement suppose qu'elle soit déjà connectée dans le tableau de bord ; cette API se contente de l'associer à la facture, elle ne connecte pas la passerelle elle-même.
- Une série récurrente peut être mise en pause, reprise, prolongée, reprogrammée et voir ses occurrences à venir ignorées via l'API, mais son contenu (articles, client, montants) ne peut pas être modifié ni la série supprimée depuis l'API ; faites-le dans le tableau de bord.
Questions frequentes#
Comment obtenir une API key Invosend ?
Créez un compte sur app.invosend.com, passez le workspace sur une offre payante, puis ouvrez Settings > API Keys et cliquez sur Generate key. La clé brute n'est affichée qu'une seule fois.
Combien coûte chaque appel API de génération ?
Chaque requête réussie consomme 1 crédit de facture du solde du workspace. Le même pool est utilisé que pour les factures créées depuis le tableau de bord.
Quelle est la limite de débit de cette API ?
La limite de débit du workspace suit la configuration de votre forfait payant. La section Rate Limit ci-dessus indique la limite actuelle de chaque forfait.