Référence de l'API
Factures
Les factures et les avoirs avec leurs lignes et leurs paiements : les rédiger, les modifier tant qu'elles sont des brouillons, les envoyer, les annuler, enregistrer des paiements, les créditer, et récupérer le PDF ou le lien de paiement.
Endpoints
-
GET
/invoicesLister les factures -
GET
/invoices/{invoice}Récupérer une facture -
POST
/invoicesCréer une facture -
PATCH
/invoices/{invoice}Modifier une facture -
POST
/invoices/{invoice}/sendEnvoyer une facture -
POST
/invoices/{invoice}/mark-sentMarquer comme envoyée (sans e-mail) -
POST
/invoices/{invoice}/cancelAnnuler une facture -
POST
/invoices/{invoice}/paymentsEnregistrer un paiement -
POST
/invoices/{invoice}/creditCréditer une facture -
POST
/invoices/{invoice}/refundedEnregistrer un remboursement -
GET
/invoices/{invoice}/pdfFacture en PDF -
GET
/invoices/{invoice}/payment-linkObtenir le lien de paiement -
DELETE
/invoices/{invoice}Supprimer une facture
Lister les factures
/api/v1/invoices
Une liste de factures, les plus récentes d'abord, avec leurs lignes et les paiements enregistrés. Filtrez par statut, client ou date de modification. Avec filter[status]=paid et filter[updated_since], vous récupérez ce qui a été payé depuis votre dernière synchronisation. Les avoirs figurent dans la même liste (type credit_note, avec des montants négatifs) ; avec filter[type], vous récupérez uniquement les factures ou uniquement les avoirs.
- Scope
-
invoices.read— Lire les factures, avec leurs lignes, leurs montants, les paiements et les coordonnées du client - Fonctionnalité requise
invoices
Paramètres de requête
| Nom | Type | Description |
|---|---|---|
limit
|
integer | Nombre de résultats par page. de 1 à 100 · par défaut : 50 |
cursor
|
string | Le next_cursor ou prev_cursor de meta dans la réponse précédente. |
sort
|
string | Le champ sur lequel trier ; un signe moins devant signifie décroissant. Les champs que vous pouvez choisir et la valeur par défaut sont indiqués avec ce paramètre. l'une des valeurs : -created_at, created_at, -updated_at, updated_at · par défaut : -created_at |
filter[status]
|
string | Uniquement les factures avec ce statut, par exemple paid, overdue ou credited. l'une des valeurs : draft, sent, viewed, paid, partial, overdue, cancelled, refunded, credited |
filter[type]
|
string | Uniquement les factures (invoice) ou uniquement les avoirs (credit_note). Sans ce filtre, vous obtenez les deux. l'une des valeurs : invoice, credit_note |
filter[customer_id]
|
string (uuid) | Uniquement ce qui appartient à ce client. |
filter[updated_since]
|
string (date-time) | Uniquement ce qui a changé depuis ce moment : ISO 8601 avec fuseau horaire, par exemple 2026-09-14T10:15:00Z. Pratique pour synchroniser. Prévoyez un chevauchement de quelques minutes avec votre moment précédent, car l'horloge de votre système et celle de Klantly ne sont pas exactement synchronisées, et car une modification juste après votre moment précédent tomberait sinon de justesse en dehors. La limite est inclusive : un élément modifié exactement à cet instant est inclus. |
Exemple de requête
curl "https://app.klantly.com/api/v1/invoices?filter[status]=paid&sort=-updated_at" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'invoices', [
'query' => [
'filter[status]' => 'paid',
'sort' => '-updated_at',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/invoices?filter[status]=paid&sort=-updated_at', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/invoices",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
params={
"filter[status]": "paid",
"sort": "-updated_at"
},
)
data = response.json()["data"]Réponse 200
La réponse est une liste avec pagination par curseur : data contient les objets, meta la pagination.
{
"data": [
{
"object": "invoice",
"id": "9d3f868b-c1a3-4c8a-9fde-e3f1a2b3c4dd",
"number": "FAC-00042",
"type": "invoice",
"status": "sent",
"title": "Veranda 400 × 300",
"description": null,
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"customer": {
"type": "business",
"name": "De Vries Bouw",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"company_name": "De Vries Bouw",
"vat_number": null,
"coc_number": null
},
"quote_id": "9d3f8449-afe1-4a6e-9dbc-c1dfe0f1a2ba",
"deal_id": null,
"language": "nl",
"currency": "EUR",
"invoice_date": "2026-09-16",
"due_date": "2026-10-16",
"payment_term_days": 30,
"is_term_invoice": false,
"term_percentage": null,
"term_amount": null,
"terms_conditions": null,
"notes": null,
"outro_text": null,
"hide_line_amounts": false,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"subtotal": "2450.00",
"tax_amount": "514.50",
"total": "2964.50",
"amount_paid": "0.00",
"amount_due": "2964.50",
"sent_at": null,
"viewed_at": null,
"paid_at": null,
"cancelled_at": null,
"credited_invoice_id": null,
"credited_invoice_number": null,
"credit_reason": null,
"refund_amount": null,
"refunded_at": null,
"credit_note_state": null,
"credited_amount": "0.00",
"credit_note_ids": [],
"items": [
{
"object": "invoice_item",
"id": "9d3f87ac-d2b4-4d9b-8aef-f4a2b3c4d5ee",
"type": "product",
"name": "Veranda",
"description": null,
"sku": null,
"quantity": "1.00",
"unit": "stuk",
"unit_price": "2450.00",
"unit_price_incl": null,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"line_total": "2450.00",
"line_total_incl": null,
"is_taxable": true,
"tax_rate": "21.00",
"credited_item_id": null
}
],
"payments": [
{
"object": "invoice_payment",
"id": "9d3f88cd-e3c5-4eac-9bf0-a5b3c4d5e6ff",
"amount": "2964.50",
"type": "full",
"status": "paid",
"payment_method": "bank_transfer",
"description": null,
"paid_at": "2026-09-16T10:15:00Z",
"created_at": "2026-09-16T10:15:00Z"
}
],
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
],
"meta": {
"limit": 50,
"next_cursor": "eyJpZCI6IjlkM2Y2YzFlIn0",
"prev_cursor": null
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
422
validation_failed— Les données saisies ne sont pas valides.
Récupérer une facture
/api/v1/invoices/{invoice}
Une facture par id, avec ses lignes, ses montants et ses paiements. La réponse contient un ETag que vous pouvez renvoyer dans If-Match lors d'une modification.
- Scope
-
invoices.read— Lire les factures, avec leurs lignes, leurs montants, les paiements et les coordonnées du client - Fonctionnalité requise
invoices
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
invoice obligatoire |
string (uuid) | L'id (UUID) de la facture. |
Exemple de requête
curl "https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "invoice",
"id": "9d3f868b-c1a3-4c8a-9fde-e3f1a2b3c4dd",
"number": "FAC-00042",
"type": "invoice",
"status": "sent",
"title": "Veranda 400 × 300",
"description": null,
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"customer": {
"type": "business",
"name": "De Vries Bouw",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"company_name": "De Vries Bouw",
"vat_number": null,
"coc_number": null
},
"quote_id": "9d3f8449-afe1-4a6e-9dbc-c1dfe0f1a2ba",
"deal_id": null,
"language": "nl",
"currency": "EUR",
"invoice_date": "2026-09-16",
"due_date": "2026-10-16",
"payment_term_days": 30,
"is_term_invoice": false,
"term_percentage": null,
"term_amount": null,
"terms_conditions": null,
"notes": null,
"outro_text": null,
"hide_line_amounts": false,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"subtotal": "2450.00",
"tax_amount": "514.50",
"total": "2964.50",
"amount_paid": "0.00",
"amount_due": "2964.50",
"sent_at": null,
"viewed_at": null,
"paid_at": null,
"cancelled_at": null,
"credited_invoice_id": null,
"credited_invoice_number": null,
"credit_reason": null,
"refund_amount": null,
"refunded_at": null,
"credit_note_state": null,
"credited_amount": "0.00",
"credit_note_ids": [],
"items": [
{
"object": "invoice_item",
"id": "9d3f87ac-d2b4-4d9b-8aef-f4a2b3c4d5ee",
"type": "product",
"name": "Veranda",
"description": null,
"sku": null,
"quantity": "1.00",
"unit": "stuk",
"unit_price": "2450.00",
"unit_price_incl": null,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"line_total": "2450.00",
"line_total_incl": null,
"is_taxable": true,
"tax_rate": "21.00",
"credited_item_id": null
}
],
"payments": [
{
"object": "invoice_payment",
"id": "9d3f88cd-e3c5-4eac-9bf0-a5b3c4d5e6ff",
"amount": "2964.50",
"type": "full",
"status": "paid",
"payment_method": "bank_transfer",
"description": null,
"paid_at": "2026-09-16T10:15:00Z",
"created_at": "2026-09-16T10:15:00Z"
}
],
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable.
Créer une facture
/api/v1/invoices
Crée une facture pour un client, toujours en brouillon. Klantly attribue le numéro et calcule les totaux ; le nom, l'adresse et les coordonnées proviennent du client. Avec quote_id, vous la reliez à un devis.
- Scope
-
invoices.write— Créer des factures (aussi à partir d'un devis) et les modifier (brouillons uniquement), les annuler, enregistrer des paiements, les créditer et enregistrer un remboursement - Fonctionnalité requise
invoices
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Corps (JSON)
| Champ | Type | Description |
|---|---|---|
customer_id
obligatoire
|
string (uuid) | Le client. Obligatoire à la création ; le nom, l'adresse et les coordonnées proviennent du client. |
title
obligatoire
|
string | Titre de la facture. Obligatoire à la création. au maximum 255 caractères |
items
obligatoire
|
array | Les lignes (200 au maximum). À l'envoi : une liste avec, par ligne, name (obligatoire) et éventuellement type, description, sku, quantity, unit, unit_price, unit_price_incl, discount_percentage, discount_amount, discount_description, tax_rate et is_taxable. Elles remplacent toutes les lignes existantes. |
quote_id
facultatif
|
string (uuid) | Le devis dont provient cette facture, ou null. peut être vide (null) |
description
facultatif
|
string | Brève description ; affichée au-dessus des lignes. peut être vide (null) · au maximum 20000 caractères |
language
facultatif
|
string | Langue de la facture : nl, en, de ou fr. l'une des valeurs : nl, en, de, fr |
invoice_date
facultatif
|
string (date) | Date de facture (AAAA-MM-JJ). |
due_date
facultatif
|
string (date) | Date d'échéance (AAAA-MM-JJ). Sans indication, c'est la date de facture plus le délai de paiement. |
payment_term_days
facultatif
|
integer | Délai de paiement en jours. Sans indication, le délai par défaut de l'entreprise s'applique. de 0 à 365 |
terms_conditions
facultatif
|
string | Conditions figurant sur la facture. peut être vide (null) · au maximum 20000 caractères |
notes
facultatif
|
string | Remarques pour le client sur la facture. Lors de l'enregistrement d'un paiement : une note sur ce paiement. peut être vide (null) · au maximum 20000 caractères |
outro_text
facultatif
|
string | Texte de clôture sous les lignes. peut être vide (null) · au maximum 20000 caractères |
hide_line_amounts
facultatif
|
boolean | Masque les montants par ligne sur la facture ; le client ne voit que le total. |
discount_percentage
facultatif
|
number | Remise sur le total, en pourcentage. de 0 à 100 |
discount_amount
facultatif
|
number | Remise sur le total, en montant. de 0 à 9999999 |
discount_description
facultatif
|
string | Pourquoi la remise a été accordée ; figure sur la facture. peut être vide (null) · au maximum 500 caractères |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/invoices" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
-d '{
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"title": "Veranda 400 × 300",
"items": [
{
"name": "Veranda",
"quantity": 1,
"unit_price": "2450.00",
"tax_rate": "21.00"
}
]
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'invoices', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
'json' => [
'customer_id' => '9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70',
'title' => 'Veranda 400 × 300',
'items' => [
0 => [
'name' => 'Veranda',
'quantity' => 1,
'unit_price' => '2450.00',
'tax_rate' => '21.00',
],
],
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/invoices', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
body: JSON.stringify({
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"title": "Veranda 400 × 300",
"items": [
{
"name": "Veranda",
"quantity": 1,
"unit_price": "2450.00",
"tax_rate": "21.00"
}
]
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/invoices",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
json={
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"title": "Veranda 400 × 300",
"items": [
{
"name": "Veranda",
"quantity": 1,
"unit_price": "2450.00",
"tax_rate": "21.00"
}
]
},
)
data = response.json()["data"]Réponse 201
{
"data": {
"object": "invoice",
"id": "9d3f868b-c1a3-4c8a-9fde-e3f1a2b3c4dd",
"number": "FAC-00042",
"type": "invoice",
"status": "sent",
"title": "Veranda 400 × 300",
"description": null,
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"customer": {
"type": "business",
"name": "De Vries Bouw",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"company_name": "De Vries Bouw",
"vat_number": null,
"coc_number": null
},
"quote_id": "9d3f8449-afe1-4a6e-9dbc-c1dfe0f1a2ba",
"deal_id": null,
"language": "nl",
"currency": "EUR",
"invoice_date": "2026-09-16",
"due_date": "2026-10-16",
"payment_term_days": 30,
"is_term_invoice": false,
"term_percentage": null,
"term_amount": null,
"terms_conditions": null,
"notes": null,
"outro_text": null,
"hide_line_amounts": false,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"subtotal": "2450.00",
"tax_amount": "514.50",
"total": "2964.50",
"amount_paid": "0.00",
"amount_due": "2964.50",
"sent_at": null,
"viewed_at": null,
"paid_at": null,
"cancelled_at": null,
"credited_invoice_id": null,
"credited_invoice_number": null,
"credit_reason": null,
"refund_amount": null,
"refunded_at": null,
"credit_note_state": null,
"credited_amount": "0.00",
"credit_note_ids": [],
"items": [
{
"object": "invoice_item",
"id": "9d3f87ac-d2b4-4d9b-8aef-f4a2b3c4d5ee",
"type": "product",
"name": "Veranda",
"description": null,
"sku": null,
"quantity": "1.00",
"unit": "stuk",
"unit_price": "2450.00",
"unit_price_incl": null,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"line_total": "2450.00",
"line_total_incl": null,
"is_taxable": true,
"tax_rate": "21.00",
"credited_item_id": null
}
],
"payments": [
{
"object": "invoice_payment",
"id": "9d3f88cd-e3c5-4eac-9bf0-a5b3c4d5e6ff",
"amount": "2964.50",
"type": "full",
"status": "paid",
"payment_method": "bank_transfer",
"description": null,
"paid_at": "2026-09-16T10:15:00Z",
"created_at": "2026-09-16T10:15:00Z"
}
],
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
422
validation_failed— Les données saisies ne sont pas valides. -
422
unknown_field— Les données contiennent un champ inconnu. -
415
unsupported_media_type— Ce format n'est pas pris en charge. -
413
payload_too_large— Le corps de la requête est trop volumineux. -
403
limit_reached— La limite de l'abonnement est atteinte. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Modifier une facture
/api/v1/invoices/{invoice}
Ne modifie que les champs que vous envoyez. items remplace toutes les lignes en bloc. Seul un brouillon peut encore changer : une fois la facture envoyée, elle se trouve dans la comptabilité du client et vous obtenez 409.
- Scope
-
invoices.write— Créer des factures (aussi à partir d'un devis) et les modifier (brouillons uniquement), les annuler, enregistrer des paiements, les créditer et enregistrer un remboursement - Fonctionnalité requise
invoices
Envoyez l'ETag dans If-Match : vous n'écraserez jamais par erreur une version plus récente.
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
invoice obligatoire |
string (uuid) | L'id (UUID) de la facture. |
Corps (JSON)
| Champ | Type | Description |
|---|---|---|
title
facultatif
|
string | Titre de la facture. Obligatoire à la création. au maximum 255 caractères |
description
facultatif
|
string | Brève description ; affichée au-dessus des lignes. peut être vide (null) · au maximum 20000 caractères |
language
facultatif
|
string | Langue de la facture : nl, en, de ou fr. l'une des valeurs : nl, en, de, fr |
invoice_date
facultatif
|
string (date) | Date de facture (AAAA-MM-JJ). |
due_date
facultatif
|
string (date) | Date d'échéance (AAAA-MM-JJ). Sans indication, c'est la date de facture plus le délai de paiement. |
payment_term_days
facultatif
|
integer | Délai de paiement en jours. Sans indication, le délai par défaut de l'entreprise s'applique. de 0 à 365 |
terms_conditions
facultatif
|
string | Conditions figurant sur la facture. peut être vide (null) · au maximum 20000 caractères |
notes
facultatif
|
string | Remarques pour le client sur la facture. Lors de l'enregistrement d'un paiement : une note sur ce paiement. peut être vide (null) · au maximum 20000 caractères |
outro_text
facultatif
|
string | Texte de clôture sous les lignes. peut être vide (null) · au maximum 20000 caractères |
hide_line_amounts
facultatif
|
boolean | Masque les montants par ligne sur la facture ; le client ne voit que le total. |
discount_percentage
facultatif
|
number | Remise sur le total, en pourcentage. de 0 à 100 |
discount_amount
facultatif
|
number | Remise sur le total, en montant. de 0 à 9999999 |
discount_description
facultatif
|
string | Pourquoi la remise a été accordée ; figure sur la facture. peut être vide (null) · au maximum 500 caractères |
items
facultatif
|
array | Les lignes (200 au maximum). À l'envoi : une liste avec, par ligne, name (obligatoire) et éventuellement type, description, sku, quantity, unit, unit_price, unit_price_incl, discount_percentage, discount_amount, discount_description, tax_rate et is_taxable. Elles remplacent toutes les lignes existantes. |
Exemple de requête
curl -X PATCH "https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"notes": "Graag betalen binnen 14 dagen."
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('PATCH', 'invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', [
'json' => [
'notes' => 'Graag betalen binnen 14 dagen.',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"notes": "Graag betalen binnen 14 dagen."
}),
});
const { data } = await response.json();import os
import requests
response = requests.patch(
"https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
json={
"notes": "Graag betalen binnen 14 dagen."
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "invoice",
"id": "9d3f868b-c1a3-4c8a-9fde-e3f1a2b3c4dd",
"number": "FAC-00042",
"type": "invoice",
"status": "sent",
"title": "Veranda 400 × 300",
"description": null,
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"customer": {
"type": "business",
"name": "De Vries Bouw",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"company_name": "De Vries Bouw",
"vat_number": null,
"coc_number": null
},
"quote_id": "9d3f8449-afe1-4a6e-9dbc-c1dfe0f1a2ba",
"deal_id": null,
"language": "nl",
"currency": "EUR",
"invoice_date": "2026-09-16",
"due_date": "2026-10-16",
"payment_term_days": 30,
"is_term_invoice": false,
"term_percentage": null,
"term_amount": null,
"terms_conditions": null,
"notes": null,
"outro_text": null,
"hide_line_amounts": false,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"subtotal": "2450.00",
"tax_amount": "514.50",
"total": "2964.50",
"amount_paid": "0.00",
"amount_due": "2964.50",
"sent_at": null,
"viewed_at": null,
"paid_at": null,
"cancelled_at": null,
"credited_invoice_id": null,
"credited_invoice_number": null,
"credit_reason": null,
"refund_amount": null,
"refunded_at": null,
"credit_note_state": null,
"credited_amount": "0.00",
"credit_note_ids": [],
"items": [
{
"object": "invoice_item",
"id": "9d3f87ac-d2b4-4d9b-8aef-f4a2b3c4d5ee",
"type": "product",
"name": "Veranda",
"description": null,
"sku": null,
"quantity": "1.00",
"unit": "stuk",
"unit_price": "2450.00",
"unit_price_incl": null,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"line_total": "2450.00",
"line_total_incl": null,
"is_taxable": true,
"tax_rate": "21.00",
"credited_item_id": null
}
],
"payments": [
{
"object": "invoice_payment",
"id": "9d3f88cd-e3c5-4eac-9bf0-a5b3c4d5e6ff",
"amount": "2964.50",
"type": "full",
"status": "paid",
"payment_method": "bank_transfer",
"description": null,
"paid_at": "2026-09-16T10:15:00Z",
"created_at": "2026-09-16T10:15:00Z"
}
],
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
422
validation_failed— Les données saisies ne sont pas valides. -
422
unknown_field— Les données contiennent un champ inconnu. -
415
unsupported_media_type— Ce format n'est pas pris en charge. -
413
payload_too_large— Le corps de la requête est trop volumineux. -
404
not_found— Introuvable. -
412
precondition_failed— L'enregistrement a été modifié entre-temps. -
409
invalid_state_transition— Cette action n'est pas possible dans le statut actuel.
Envoyer une facture
/api/v1/invoices/{invoice}/send
Envoie la facture par e-mail au client avec le modèle de notification de l'entreprise et passe le statut à envoyée. Un nouvel envoi compte comme un rappel : reminder_count augmente. Pour un avoir ou une facture (partiellement) créditée, le statut reste inchangé ; seul sent_at est mis à jour.
- Scope
-
invoices.send— Envoyer les factures par e-mail aux clients et obtenir le lien de paiement pour le client - Fonctionnalité requise
invoices
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
invoice obligatoire |
string (uuid) | L'id (UUID) de la facture. |
Corps (JSON)
| Champ | Type | Description |
|---|---|---|
message
facultatif
|
string | Message personnel dans l'e-mail au client. peut être vide (null) · au maximum 5000 caractères |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/send" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
-d '{
"message": "Bijgaand de factuur voor de geplaatste veranda."
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/send', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
'json' => [
'message' => 'Bijgaand de factuur voor de geplaatste veranda.',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/send', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
body: JSON.stringify({
"message": "Bijgaand de factuur voor de geplaatste veranda."
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/send",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
json={
"message": "Bijgaand de factuur voor de geplaatste veranda."
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "invoice",
"id": "9d3f868b-c1a3-4c8a-9fde-e3f1a2b3c4dd",
"number": "FAC-00042",
"type": "invoice",
"status": "sent",
"title": "Veranda 400 × 300",
"description": null,
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"customer": {
"type": "business",
"name": "De Vries Bouw",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"company_name": "De Vries Bouw",
"vat_number": null,
"coc_number": null
},
"quote_id": "9d3f8449-afe1-4a6e-9dbc-c1dfe0f1a2ba",
"deal_id": null,
"language": "nl",
"currency": "EUR",
"invoice_date": "2026-09-16",
"due_date": "2026-10-16",
"payment_term_days": 30,
"is_term_invoice": false,
"term_percentage": null,
"term_amount": null,
"terms_conditions": null,
"notes": null,
"outro_text": null,
"hide_line_amounts": false,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"subtotal": "2450.00",
"tax_amount": "514.50",
"total": "2964.50",
"amount_paid": "0.00",
"amount_due": "2964.50",
"sent_at": null,
"viewed_at": null,
"paid_at": null,
"cancelled_at": null,
"credited_invoice_id": null,
"credited_invoice_number": null,
"credit_reason": null,
"refund_amount": null,
"refunded_at": null,
"credit_note_state": null,
"credited_amount": "0.00",
"credit_note_ids": [],
"items": [
{
"object": "invoice_item",
"id": "9d3f87ac-d2b4-4d9b-8aef-f4a2b3c4d5ee",
"type": "product",
"name": "Veranda",
"description": null,
"sku": null,
"quantity": "1.00",
"unit": "stuk",
"unit_price": "2450.00",
"unit_price_incl": null,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"line_total": "2450.00",
"line_total_incl": null,
"is_taxable": true,
"tax_rate": "21.00",
"credited_item_id": null
}
],
"payments": [
{
"object": "invoice_payment",
"id": "9d3f88cd-e3c5-4eac-9bf0-a5b3c4d5e6ff",
"amount": "2964.50",
"type": "full",
"status": "paid",
"payment_method": "bank_transfer",
"description": null,
"paid_at": "2026-09-16T10:15:00Z",
"created_at": "2026-09-16T10:15:00Z"
}
],
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
422
validation_failed— Les données saisies ne sont pas valides. -
422
unknown_field— Les données contiennent un champ inconnu. -
415
unsupported_media_type— Ce format n'est pas pris en charge. -
413
payload_too_large— Le corps de la requête est trop volumineux. -
404
not_found— Introuvable. -
403
forbidden— Accès refusé. -
409
invalid_state_transition— Cette action n'est pas possible dans le statut actuel. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Marquer comme envoyée (sans e-mail)
/api/v1/invoices/{invoice}/mark-sent
Passe un brouillon à envoyée sans que Klantly envoie d'e-mail au client, comme le bouton dans l'application. Utilisez ceci si vous avez remis la facture vous-même : par votre propre e-mail, sur papier ou via votre logiciel comptable. sent_at est rempli et l'événement invoice.sent suit. Vous pouvez ensuite y enregistrer un paiement. Si la facture est déjà envoyée ou plus avancée, elle est renvoyée inchangée ; un brouillon annulé donne 409. Envoyez une Idempotency-Key.
- Scope
-
invoices.write— Créer des factures (aussi à partir d'un devis) et les modifier (brouillons uniquement), les annuler, enregistrer des paiements, les créditer et enregistrer un remboursement - Fonctionnalité requise
invoices
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
invoice obligatoire |
string (uuid) | L'id (UUID) de la facture. |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/mark-sent" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/mark-sent', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/mark-sent', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/mark-sent",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "invoice",
"id": "9d3f868b-c1a3-4c8a-9fde-e3f1a2b3c4dd",
"number": "FAC-00042",
"type": "invoice",
"status": "sent",
"title": "Veranda 400 × 300",
"description": null,
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"customer": {
"type": "business",
"name": "De Vries Bouw",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"company_name": "De Vries Bouw",
"vat_number": null,
"coc_number": null
},
"quote_id": "9d3f8449-afe1-4a6e-9dbc-c1dfe0f1a2ba",
"deal_id": null,
"language": "nl",
"currency": "EUR",
"invoice_date": "2026-09-16",
"due_date": "2026-10-16",
"payment_term_days": 30,
"is_term_invoice": false,
"term_percentage": null,
"term_amount": null,
"terms_conditions": null,
"notes": null,
"outro_text": null,
"hide_line_amounts": false,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"subtotal": "2450.00",
"tax_amount": "514.50",
"total": "2964.50",
"amount_paid": "0.00",
"amount_due": "2964.50",
"sent_at": null,
"viewed_at": null,
"paid_at": null,
"cancelled_at": null,
"credited_invoice_id": null,
"credited_invoice_number": null,
"credit_reason": null,
"refund_amount": null,
"refunded_at": null,
"credit_note_state": null,
"credited_amount": "0.00",
"credit_note_ids": [],
"items": [
{
"object": "invoice_item",
"id": "9d3f87ac-d2b4-4d9b-8aef-f4a2b3c4d5ee",
"type": "product",
"name": "Veranda",
"description": null,
"sku": null,
"quantity": "1.00",
"unit": "stuk",
"unit_price": "2450.00",
"unit_price_incl": null,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"line_total": "2450.00",
"line_total_incl": null,
"is_taxable": true,
"tax_rate": "21.00",
"credited_item_id": null
}
],
"payments": [
{
"object": "invoice_payment",
"id": "9d3f88cd-e3c5-4eac-9bf0-a5b3c4d5e6ff",
"amount": "2964.50",
"type": "full",
"status": "paid",
"payment_method": "bank_transfer",
"description": null,
"paid_at": "2026-09-16T10:15:00Z",
"created_at": "2026-09-16T10:15:00Z"
}
],
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
409
invalid_state_transition— Cette action n'est pas possible dans le statut actuel. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Annuler une facture
/api/v1/invoices/{invoice}/cancel
Passe la facture en annulée. Une facture payée ou (partiellement) créditée ne peut pas être annulée (409) ; corrigez une facture envoyée avec Créditer une facture.
- Scope
-
invoices.write— Créer des factures (aussi à partir d'un devis) et les modifier (brouillons uniquement), les annuler, enregistrer des paiements, les créditer et enregistrer un remboursement - Fonctionnalité requise
invoices
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
invoice obligatoire |
string (uuid) | L'id (UUID) de la facture. |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/cancel" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/cancel', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/cancel', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/cancel",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "invoice",
"id": "9d3f868b-c1a3-4c8a-9fde-e3f1a2b3c4dd",
"number": "FAC-00042",
"type": "invoice",
"status": "sent",
"title": "Veranda 400 × 300",
"description": null,
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"customer": {
"type": "business",
"name": "De Vries Bouw",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"company_name": "De Vries Bouw",
"vat_number": null,
"coc_number": null
},
"quote_id": "9d3f8449-afe1-4a6e-9dbc-c1dfe0f1a2ba",
"deal_id": null,
"language": "nl",
"currency": "EUR",
"invoice_date": "2026-09-16",
"due_date": "2026-10-16",
"payment_term_days": 30,
"is_term_invoice": false,
"term_percentage": null,
"term_amount": null,
"terms_conditions": null,
"notes": null,
"outro_text": null,
"hide_line_amounts": false,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"subtotal": "2450.00",
"tax_amount": "514.50",
"total": "2964.50",
"amount_paid": "0.00",
"amount_due": "2964.50",
"sent_at": null,
"viewed_at": null,
"paid_at": null,
"cancelled_at": null,
"credited_invoice_id": null,
"credited_invoice_number": null,
"credit_reason": null,
"refund_amount": null,
"refunded_at": null,
"credit_note_state": null,
"credited_amount": "0.00",
"credit_note_ids": [],
"items": [
{
"object": "invoice_item",
"id": "9d3f87ac-d2b4-4d9b-8aef-f4a2b3c4d5ee",
"type": "product",
"name": "Veranda",
"description": null,
"sku": null,
"quantity": "1.00",
"unit": "stuk",
"unit_price": "2450.00",
"unit_price_incl": null,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"line_total": "2450.00",
"line_total_incl": null,
"is_taxable": true,
"tax_rate": "21.00",
"credited_item_id": null
}
],
"payments": [
{
"object": "invoice_payment",
"id": "9d3f88cd-e3c5-4eac-9bf0-a5b3c4d5e6ff",
"amount": "2964.50",
"type": "full",
"status": "paid",
"payment_method": "bank_transfer",
"description": null,
"paid_at": "2026-09-16T10:15:00Z",
"created_at": "2026-09-16T10:15:00Z"
}
],
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
409
invalid_state_transition— Cette action n'est pas possible dans le statut actuel. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Enregistrer un paiement
/api/v1/invoices/{invoice}/payments
Enregistre un paiement reçu en dehors de Klantly, par exemple un virement. Le montant ne peut jamais dépasser le montant restant dû. Si la facture est ainsi entièrement réglée, elle passe à payée et l'événement invoice.paid suit.
- Scope
-
invoices.write— Créer des factures (aussi à partir d'un devis) et les modifier (brouillons uniquement), les annuler, enregistrer des paiements, les créditer et enregistrer un remboursement - Fonctionnalité requise
invoices
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
invoice obligatoire |
string (uuid) | L'id (UUID) de la facture. |
Corps (JSON)
| Champ | Type | Description |
|---|---|---|
amount
obligatoire
|
number | Le montant du paiement que vous enregistrez. Jamais plus que le montant restant dû. de 0 à 9999999 |
payment_method
facultatif
|
string | Comment le paiement a été effectué : bank_transfer, cash, card, ideal, credit_card, paypal, bancontact ou other. l'une des valeurs : bank_transfer, cash, card, ideal, credit_card, paypal, bancontact, other |
reference
facultatif
|
string | Votre propre référence pour le paiement, par exemple le relevé bancaire ou l'id de transaction. peut être vide (null) · au maximum 255 caractères |
notes
facultatif
|
string | Remarques pour le client sur la facture. Lors de l'enregistrement d'un paiement : une note sur ce paiement. peut être vide (null) · au maximum 1000 caractères |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/payments" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
-d '{
"amount": "2964.50",
"payment_method": "bank_transfer",
"reference": "NL02ABNA0123456789"
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/payments', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
'json' => [
'amount' => '2964.50',
'payment_method' => 'bank_transfer',
'reference' => 'NL02ABNA0123456789',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/payments', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
body: JSON.stringify({
"amount": "2964.50",
"payment_method": "bank_transfer",
"reference": "NL02ABNA0123456789"
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/payments",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
json={
"amount": "2964.50",
"payment_method": "bank_transfer",
"reference": "NL02ABNA0123456789"
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "invoice",
"id": "9d3f868b-c1a3-4c8a-9fde-e3f1a2b3c4dd",
"number": "FAC-00042",
"type": "invoice",
"status": "sent",
"title": "Veranda 400 × 300",
"description": null,
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"customer": {
"type": "business",
"name": "De Vries Bouw",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"company_name": "De Vries Bouw",
"vat_number": null,
"coc_number": null
},
"quote_id": "9d3f8449-afe1-4a6e-9dbc-c1dfe0f1a2ba",
"deal_id": null,
"language": "nl",
"currency": "EUR",
"invoice_date": "2026-09-16",
"due_date": "2026-10-16",
"payment_term_days": 30,
"is_term_invoice": false,
"term_percentage": null,
"term_amount": null,
"terms_conditions": null,
"notes": null,
"outro_text": null,
"hide_line_amounts": false,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"subtotal": "2450.00",
"tax_amount": "514.50",
"total": "2964.50",
"amount_paid": "0.00",
"amount_due": "2964.50",
"sent_at": null,
"viewed_at": null,
"paid_at": null,
"cancelled_at": null,
"credited_invoice_id": null,
"credited_invoice_number": null,
"credit_reason": null,
"refund_amount": null,
"refunded_at": null,
"credit_note_state": null,
"credited_amount": "0.00",
"credit_note_ids": [],
"items": [
{
"object": "invoice_item",
"id": "9d3f87ac-d2b4-4d9b-8aef-f4a2b3c4d5ee",
"type": "product",
"name": "Veranda",
"description": null,
"sku": null,
"quantity": "1.00",
"unit": "stuk",
"unit_price": "2450.00",
"unit_price_incl": null,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"line_total": "2450.00",
"line_total_incl": null,
"is_taxable": true,
"tax_rate": "21.00",
"credited_item_id": null
}
],
"payments": [
{
"object": "invoice_payment",
"id": "9d3f88cd-e3c5-4eac-9bf0-a5b3c4d5e6ff",
"amount": "2964.50",
"type": "full",
"status": "paid",
"payment_method": "bank_transfer",
"description": null,
"paid_at": "2026-09-16T10:15:00Z",
"created_at": "2026-09-16T10:15:00Z"
}
],
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
422
validation_failed— Les données saisies ne sont pas valides. -
422
unknown_field— Les données contiennent un champ inconnu. -
415
unsupported_media_type— Ce format n'est pas pris en charge. -
413
payload_too_large— Le corps de la requête est trop volumineux. -
404
not_found— Introuvable. -
409
invalid_state_transition— Cette action n'est pas possible dans le statut actuel. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Créditer une facture
/api/v1/invoices/{invoice}/credit
Crée un avoir sur une facture envoyée ou payée, comme le bouton dans l'application. mode=full crédite tout ce qui n'a pas encore été crédité, mode=lines une quantité par ligne (lines[].item_id et lines[].quantity) et mode=amount un montant libre TTC à un taux de TVA présent sur la facture. La réponse (201) est l'avoir : une invoice avec type credit_note, des lignes et totaux négatifs et credited_invoice_id. La partie qui peut être imputée sur le montant restant dû l'est ; le reste figure sur l'avoir en refund_amount et doit être remboursé au client. Créditer plus que ce qui reste sur la facture donne 422 sur amount, lines ou lines.N.quantity ; un brouillon, une facture annulée ou déjà entièrement créditée, ou un avoir, donne 409. Suivent les événements invoice.created (l'avoir) et invoice.credited (la facture). Envoyez toujours une Idempotency-Key.
- Scope
-
invoices.write— Créer des factures (aussi à partir d'un devis) et les modifier (brouillons uniquement), les annuler, enregistrer des paiements, les créditer et enregistrer un remboursement - Fonctionnalité requise
invoices
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
invoice obligatoire |
string (uuid) | L'id (UUID) de la facture. |
Corps (JSON)
| Champ | Type | Description |
|---|---|---|
mode
obligatoire
|
string | Ce que vous créditez : full (tout ce qui n'a pas encore été crédité), lines (une quantité par ligne) ou amount (un montant libre). l'une des valeurs : full, lines, amount |
reason
obligatoire
|
string | Le motif de l'avoir (obligatoire, 500 caractères au maximum) ; figure sur l'avoir. au maximum 500 caractères |
lines
facultatif
|
array | Avec mode=lines : les lignes que vous créditez, chacune avec item_id et quantity. |
amount
facultatif
|
number | Avec mode=amount : le montant TTC que vous créditez. Jamais plus que ce qui peut encore être crédité sur la facture. de 0 à 9999999 |
tax_rate
facultatif
|
number | Avec mode=amount : le taux de TVA de ce montant. Doit figurer sur la facture ; sans indication, le premier taux de la facture. peut être vide (null) · de 0 à 100 |
invoice_date
facultatif
|
string (date) | Date de l'avoir (AAAA-MM-JJ) ; par défaut aujourd'hui. |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/credit" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
-d '{
"mode": "amount",
"reason": "Korting na klacht over de montage",
"amount": "150.00",
"tax_rate": "21.00"
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/credit', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
'json' => [
'mode' => 'amount',
'reason' => 'Korting na klacht over de montage',
'amount' => '150.00',
'tax_rate' => '21.00',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/credit', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
body: JSON.stringify({
"mode": "amount",
"reason": "Korting na klacht over de montage",
"amount": "150.00",
"tax_rate": "21.00"
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/credit",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
json={
"mode": "amount",
"reason": "Korting na klacht over de montage",
"amount": "150.00",
"tax_rate": "21.00"
},
)
data = response.json()["data"]Réponse 201
{
"data": {
"object": "invoice",
"id": "9d3f868b-c1a3-4c8a-9fde-e3f1a2b3c4dd",
"number": "FAC-00042",
"type": "invoice",
"status": "sent",
"title": "Veranda 400 × 300",
"description": null,
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"customer": {
"type": "business",
"name": "De Vries Bouw",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"company_name": "De Vries Bouw",
"vat_number": null,
"coc_number": null
},
"quote_id": "9d3f8449-afe1-4a6e-9dbc-c1dfe0f1a2ba",
"deal_id": null,
"language": "nl",
"currency": "EUR",
"invoice_date": "2026-09-16",
"due_date": "2026-10-16",
"payment_term_days": 30,
"is_term_invoice": false,
"term_percentage": null,
"term_amount": null,
"terms_conditions": null,
"notes": null,
"outro_text": null,
"hide_line_amounts": false,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"subtotal": "2450.00",
"tax_amount": "514.50",
"total": "2964.50",
"amount_paid": "0.00",
"amount_due": "2964.50",
"sent_at": null,
"viewed_at": null,
"paid_at": null,
"cancelled_at": null,
"credited_invoice_id": null,
"credited_invoice_number": null,
"credit_reason": null,
"refund_amount": null,
"refunded_at": null,
"credit_note_state": null,
"credited_amount": "0.00",
"credit_note_ids": [],
"items": [
{
"object": "invoice_item",
"id": "9d3f87ac-d2b4-4d9b-8aef-f4a2b3c4d5ee",
"type": "product",
"name": "Veranda",
"description": null,
"sku": null,
"quantity": "1.00",
"unit": "stuk",
"unit_price": "2450.00",
"unit_price_incl": null,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"line_total": "2450.00",
"line_total_incl": null,
"is_taxable": true,
"tax_rate": "21.00",
"credited_item_id": null
}
],
"payments": [
{
"object": "invoice_payment",
"id": "9d3f88cd-e3c5-4eac-9bf0-a5b3c4d5e6ff",
"amount": "2964.50",
"type": "full",
"status": "paid",
"payment_method": "bank_transfer",
"description": null,
"paid_at": "2026-09-16T10:15:00Z",
"created_at": "2026-09-16T10:15:00Z"
}
],
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
422
validation_failed— Les données saisies ne sont pas valides. -
422
unknown_field— Les données contiennent un champ inconnu. -
415
unsupported_media_type— Ce format n'est pas pris en charge. -
413
payload_too_large— Le corps de la requête est trop volumineux. -
404
not_found— Introuvable. -
409
invalid_state_transition— Cette action n'est pas possible dans le statut actuel. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Enregistrer un remboursement
/api/v1/invoices/{invoice}/refunded
Enregistre que la partie à rembourser d'un avoir (refund_amount) a été virée au client ; refunded_at est rempli et credit_note_state devient refunded. Uniquement sur un avoir avec credit_note_state refund_pending, sinon 409. Avec via=mollie, Klantly rembourse réellement le montant via Mollie (uniquement si la facture a été suffisamment payée via Mollie, sinon 409) ; si Mollie refuse, 422 sur refund. Après un remboursement partiel, credit_note_state reste refund_pending et un nouvel appel ne rembourse que le reste.
- Scope
-
invoices.write— Créer des factures (aussi à partir d'un devis) et les modifier (brouillons uniquement), les annuler, enregistrer des paiements, les créditer et enregistrer un remboursement - Fonctionnalité requise
invoices
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
invoice obligatoire |
string (uuid) | L'id (UUID) de la facture. |
Corps (JSON)
| Champ | Type | Description |
|---|---|---|
via
facultatif
|
string | manual (par défaut) : enregistrer seulement que vous avez remboursé vous-même. mollie : rembourser réellement via le ou les paiements Mollie de la facture d'origine. l'une des valeurs : manual, mollie |
payment_method
facultatif
|
string | Comment le remboursement a été effectué : bank_transfer, cash, card, ideal, credit_card, paypal, bancontact ou other. l'une des valeurs : bank_transfer, cash, card, ideal, credit_card, paypal, bancontact, other |
reference
facultatif
|
string | Votre propre référence pour le remboursement, par exemple le relevé bancaire. peut être vide (null) · au maximum 255 caractères |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/refunded" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
-d '{
"payment_method": "bank_transfer",
"reference": "NL02ABNA0123456789"
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/refunded', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
'json' => [
'payment_method' => 'bank_transfer',
'reference' => 'NL02ABNA0123456789',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/refunded', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
body: JSON.stringify({
"payment_method": "bank_transfer",
"reference": "NL02ABNA0123456789"
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/refunded",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
json={
"payment_method": "bank_transfer",
"reference": "NL02ABNA0123456789"
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "invoice",
"id": "9d3f868b-c1a3-4c8a-9fde-e3f1a2b3c4dd",
"number": "FAC-00042",
"type": "invoice",
"status": "sent",
"title": "Veranda 400 × 300",
"description": null,
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"customer": {
"type": "business",
"name": "De Vries Bouw",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"company_name": "De Vries Bouw",
"vat_number": null,
"coc_number": null
},
"quote_id": "9d3f8449-afe1-4a6e-9dbc-c1dfe0f1a2ba",
"deal_id": null,
"language": "nl",
"currency": "EUR",
"invoice_date": "2026-09-16",
"due_date": "2026-10-16",
"payment_term_days": 30,
"is_term_invoice": false,
"term_percentage": null,
"term_amount": null,
"terms_conditions": null,
"notes": null,
"outro_text": null,
"hide_line_amounts": false,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"subtotal": "2450.00",
"tax_amount": "514.50",
"total": "2964.50",
"amount_paid": "0.00",
"amount_due": "2964.50",
"sent_at": null,
"viewed_at": null,
"paid_at": null,
"cancelled_at": null,
"credited_invoice_id": null,
"credited_invoice_number": null,
"credit_reason": null,
"refund_amount": null,
"refunded_at": null,
"credit_note_state": null,
"credited_amount": "0.00",
"credit_note_ids": [],
"items": [
{
"object": "invoice_item",
"id": "9d3f87ac-d2b4-4d9b-8aef-f4a2b3c4d5ee",
"type": "product",
"name": "Veranda",
"description": null,
"sku": null,
"quantity": "1.00",
"unit": "stuk",
"unit_price": "2450.00",
"unit_price_incl": null,
"discount_percentage": "0.00",
"discount_amount": "0.00",
"discount_description": null,
"line_total": "2450.00",
"line_total_incl": null,
"is_taxable": true,
"tax_rate": "21.00",
"credited_item_id": null
}
],
"payments": [
{
"object": "invoice_payment",
"id": "9d3f88cd-e3c5-4eac-9bf0-a5b3c4d5e6ff",
"amount": "2964.50",
"type": "full",
"status": "paid",
"payment_method": "bank_transfer",
"description": null,
"paid_at": "2026-09-16T10:15:00Z",
"created_at": "2026-09-16T10:15:00Z"
}
],
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
422
validation_failed— Les données saisies ne sont pas valides. -
422
unknown_field— Les données contiennent un champ inconnu. -
415
unsupported_media_type— Ce format n'est pas pris en charge. -
413
payload_too_large— Le corps de la requête est trop volumineux. -
404
not_found— Introuvable. -
409
conflict— Ceci est en conflit avec l'état actuel. -
409
invalid_state_transition— Cette action n'est pas possible dans le statut actuel. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Facture en PDF
/api/v1/invoices/{invoice}/pdf
Renvoie la facture en PDF, telle que le client la reçoit : à la charte de l'entreprise et dans la langue de la facture. Pratique pour la joindre à l'écriture dans votre comptabilité. La première fois, Klantly la génère ; ensuite elle vient du cache jusqu'à ce que la facture change. Compte dans la limite renforcée.
- Scope
-
invoices.read— Lire les factures, avec leurs lignes, leurs montants, les paiements et les coordonnées du client - Fonctionnalité requise
invoices
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
invoice obligatoire |
string (uuid) | L'id (UUID) de la facture. |
Exemple de requête
curl "https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/pdf" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-o document.pdf$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/pdf');
file_put_contents('document.pdf', (string) $response->getBody());import { writeFile } from 'node:fs/promises';
const response = await fetch('https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/pdf', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
await writeFile('document.pdf', Buffer.from(await response.arrayBuffer()));import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/pdf",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
with open("document.pdf", "wb") as pdf:
pdf.write(response.content)Réponse 200
La réponse est le fichier lui-même (application/pdf), pas du JSON. Content-Disposition contient le nom du fichier.
Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable.
Obtenir le lien de paiement
/api/v1/invoices/{invoice}/payment-link
Renvoie la page où le client paie la facture en ligne avec Mollie, à partager vous-même, par exemple dans votre propre rappel ou via WhatsApp. Avec un échéancier, le client y choisit la prochaine échéance. Uniquement pour une facture envoyée et pas encore entièrement payée (sinon 409 invalid_state_transition) et si l'entreprise a connecté Mollie (sinon 409 conflict). Nécessite la fonctionnalité Paiements en ligne. Toute personne qui a le lien peut consulter et payer la facture : d'où le scope invoices.send.
- Scope
-
invoices.send— Envoyer les factures par e-mail aux clients et obtenir le lien de paiement pour le client - Fonctionnalité requise
invoices, invoice_payments
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
invoice obligatoire |
string (uuid) | L'id (UUID) de la facture. |
Exemple de requête
curl "https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/payment-link" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/payment-link');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/payment-link', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/payment-link",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "invoice_payment_link",
"invoice_id": "9d3f868b-c1a3-4c8a-9fde-e3f1a2b3c4dd",
"url": "https://app.klantly.com/invoice/Xk2p9Qm4Rt7vB1nC8dE5fG3hJ6kL0mN2pQ4rS7tU9vW1xY3zA5bC7dE9fG1hJ3kL/pay",
"amount_due": "1943.00",
"currency": "EUR"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
409
invalid_state_transition— Cette action n'est pas possible dans le statut actuel. -
409
conflict— Ceci est en conflit avec l'état actuel.
Supprimer une facture
/api/v1/invoices/{invoice}
Supprime la facture. Seul un brouillon peut être supprimé : une facture envoyée reste.
- Scope
-
invoices.delete— Supprimer les factures brouillon - Fonctionnalité requise
invoices
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
invoice obligatoire |
string (uuid) | L'id (UUID) de la facture. |
Exemple de requête
curl -X DELETE "https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('DELETE', 'invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.delete(
"https://app.klantly.com/api/v1/invoices/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "note",
"id": "9d3f7b41-2d6f-4e8c-9b3a-4f5d6e7a8b92",
"deleted": true
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
409
invalid_state_transition— Cette action n'est pas possible dans le statut actuel.
L'objet
Tous les champs sont toujours présents ; un champ sans valeur vaut null.
| Champ | Type | Description |
|---|---|---|
object |
string | Toujours "invoice". |
id |
string (uuid) | Id unique (UUID). |
number |
string | Numéro de facture, par exemple FAC-00042 ; attribué par Klantly. |
type |
string | invoice (facture) ou credit_note (avoir). Un avoir a des lignes et des totaux négatifs. l'une des valeurs : invoice, credit_note |
status |
string | draft (brouillon), sent (envoyée), viewed (consultée), paid (payée), partial (partiellement payée), overdue (en retard), cancelled (annulée), refunded (remboursée) ou credited (créditée : entièrement contrepassée, ne compte ni comme payée ni comme restant due). l'une des valeurs : draft, sent, viewed, paid, partial, overdue, cancelled, refunded, credited |
title |
string | Titre de la facture. Obligatoire à la création. peut être vide (null) |
description |
string | Brève description ; affichée au-dessus des lignes. peut être vide (null) |
customer_id |
string (uuid) | Le client. Obligatoire à la création ; le nom, l'adresse et les coordonnées proviennent du client. peut être vide (null) |
customer |
object | Les coordonnées du client sur la facture, telles qu'elles étaient à la création. |
customer.type |
string | individual (particulier) ou business (entreprise). peut être vide (null) |
customer.name |
string | Nom ; pour une entreprise, la raison sociale. peut être vide (null) |
customer.email |
string | Adresse e-mail. peut être vide (null) |
customer.phone |
string | Numéro de téléphone. peut être vide (null) |
customer.address |
string | Rue et numéro. peut être vide (null) |
customer.postal_code |
string | Code postal. peut être vide (null) |
customer.city |
string | Ville. peut être vide (null) |
customer.country |
string | Pays. peut être vide (null) |
customer.company_name |
string | Raison sociale. peut être vide (null) |
customer.vat_number |
string | Numéro de TVA. peut être vide (null) |
customer.coc_number |
string | Numéro d'immatriculation. peut être vide (null) |
quote_id |
string (uuid) | Le devis dont provient cette facture, ou null. peut être vide (null) |
deal_id |
string (uuid) | L'affaire du pipeline à laquelle cette facture appartient, ou null. peut être vide (null) |
language |
string | Langue de la facture : nl, en, de ou fr. l'une des valeurs : nl, en, de, fr |
currency |
string | Toujours "EUR". |
invoice_date |
string (date) | Date de facture (AAAA-MM-JJ). peut être vide (null) |
due_date |
string (date) | Date d'échéance (AAAA-MM-JJ). Sans indication, c'est la date de facture plus le délai de paiement. peut être vide (null) |
payment_term_days |
integer | Délai de paiement en jours. Sans indication, le délai par défaut de l'entreprise s'applique. peut être vide (null) |
is_term_invoice |
boolean | S'il s'agit d'une facture partielle portant sur une partie d'un devis. |
term_percentage |
string | La part du devis couverte par cette facture partielle, en pourcentage ; sinon null. peut être vide (null) |
term_amount |
string | Montant d'échéance fixe TVA comprise (égal au total de la facture) lorsque l'échéance est définie en montant et non en pourcentage ; sinon null. peut être vide (null) |
terms_conditions |
string | Conditions figurant sur la facture. peut être vide (null) |
notes |
string | Remarques pour le client sur la facture. Lors de l'enregistrement d'un paiement : une note sur ce paiement. peut être vide (null) |
outro_text |
string | Texte de clôture sous les lignes. peut être vide (null) |
hide_line_amounts |
boolean | Masque les montants par ligne sur la facture ; le client ne voit que le total. |
discount_percentage |
string | Remise sur le total, en pourcentage. |
discount_amount |
string | Remise sur le total, en montant. |
discount_description |
string | Pourquoi la remise a été accordée ; figure sur la facture. peut être vide (null) |
subtotal |
string | Total hors TVA, sous forme de texte à deux décimales. |
tax_amount |
string | Montant de la TVA. |
total |
string | Total TTC. |
amount_paid |
string | Ce qui a été payé jusqu'à présent. |
amount_due |
string | Ce qui reste dû. Après un avoir sur une facture payée, cette valeur est plafonnée à 0,00 ; le montant à rembourser figure alors sur l'avoir (refund_amount, credit_note_state). |
sent_at |
string (date-time) | Quand la facture a été envoyée au client. peut être vide (null) |
viewed_at |
string (date-time) | Quand le client l'a ouverte. peut être vide (null) |
paid_at |
string (date-time) | Quand la facture a été entièrement réglée. peut être vide (null) |
cancelled_at |
string (date-time) | Quand la facture a été annulée. peut être vide (null) |
credited_invoice_id |
string (uuid) | Pour un avoir : la facture qu'il contrepasse ; sinon null. peut être vide (null) |
credited_invoice_number |
string | Pour un avoir : le numéro de la facture créditée, figé à la création ; sinon null. peut être vide (null) |
credit_reason |
string | Pour un avoir : le motif de l'avoir ; sinon null. peut être vide (null) |
refund_amount |
string | Pour un avoir : la partie qui n'a pas pu être imputée sur le montant restant dû et doit être remboursée au client (positive) ; null pour une facture. peut être vide (null) |
refunded_at |
string (date-time) | Pour un avoir : quand le remboursement a été enregistré ; sinon null. peut être vide (null) |
credit_note_state |
string | Pour un avoir : refund_pending (de l'argent doit encore être rendu), refunded (remboursé) ou settled (entièrement imputé sur la facture) ; null pour une facture. peut être vide (null) · l'une des valeurs : refund_pending, refunded, settled |
credited_amount |
string | Pour une facture : le total contrepassé par des avoirs, TTC (positif). amount_due est le total moins le payé moins le crédité. |
credit_note_ids |
array<string> | Pour une facture : les identifiants de ses avoirs, du plus ancien au plus récent ; une liste vide pour un avoir. |
items |
array<object> | Les lignes (200 au maximum). À l'envoi : une liste avec, par ligne, name (obligatoire) et éventuellement type, description, sku, quantity, unit, unit_price, unit_price_incl, discount_percentage, discount_amount, discount_description, tax_rate et is_taxable. Elles remplacent toutes les lignes existantes. |
items.object |
string | Toujours "invoice_item". |
items.id |
string (uuid) | Id unique de la ligne (UUID). |
items.type |
string | product, service, expense, discount ou custom (un montant libre sur un avoir). l'une des valeurs : product, service, expense, discount, custom |
items.name |
string | Nom de la ligne. |
items.description |
string | Description sous la ligne. peut être vide (null) |
items.sku |
string | Référence article. peut être vide (null) |
items.quantity |
string | Quantité. |
items.unit |
string | Unité, par exemple pièce ou heure. peut être vide (null) |
items.unit_price |
string | Prix unitaire, hors TVA. |
items.unit_price_incl |
string | Prix unitaire TVA comprise, tel que saisi. S'il est renseigné, la ligne est calculée à partir de ce montant (unit_price et line_total en sont déduits) et le total correspond au centime près au prix saisi. null = la ligne est calculée à partir de unit_price. peut être vide (null) |
items.discount_percentage |
string | Remise sur cette ligne, en pourcentage. |
items.discount_amount |
string | Remise sur cette ligne, en montant. |
items.discount_description |
string | Pourquoi la remise sur cette ligne a été accordée. peut être vide (null) |
items.line_total |
string | Total de la ligne hors TVA, après remise. |
items.line_total_incl |
string | Total de la ligne TVA comprise, après remise. Renseigné uniquement si la ligne est calculée à partir de unit_price_incl ; sinon null. peut être vide (null) |
items.is_taxable |
boolean | Si cette ligne compte pour la TVA. |
items.tax_rate |
string | Taux de TVA de cette ligne, en pourcentage. |
items.credited_item_id |
string (uuid) | Sur un avoir : la ligne de facture que cette ligne contrepasse ; null pour un montant libre ou sur une facture. peut être vide (null) |
payments |
array<object> | Les paiements enregistrés sur cette facture, les plus anciens d'abord. |
payments.object |
string | Toujours "invoice_payment". |
payments.id |
string (uuid) | Id unique du paiement. |
payments.amount |
string | Le montant payé. |
payments.type |
string | full (intégral), deposit (acompte) ou partial (paiement partiel). l'une des valeurs : full, deposit, partial |
payments.status |
string | open, pending, paid, failed, expired, cancelled ou refunded. l'une des valeurs : open, pending, paid, failed, expired, cancelled, refunded |
payments.payment_method |
string | Comment le paiement a été effectué, par exemple bank_transfer ou ideal. peut être vide (null) |
payments.description |
string | Note sur le paiement. peut être vide (null) |
payments.paid_at |
string (date-time) | Quand le paiement est arrivé. peut être vide (null) |
payments.created_at |
string (date-time) | Quand le paiement a été enregistré. |
created_at |
string (date-time) | Quand la facture a été créée. |
updated_at |
string (date-time) | Quand la facture a été modifiée pour la dernière fois. |