Aller au contenu
Thème
Français

API relevé bancaire

Convertissez vos relevés CAMT.053 et MT940 par API en CSV ou XLSX. Une seconde requête peut être nécessaire si une information manque.

Cette fonction est en bêta : elle fonctionne et elle est testée, mais des détails peuvent encore changer.

Sur cette page

L’API relevé bancaire de Klarbon convertit les fichiers CAMT.053 et MT940 que les banques fournissent déjà en CSV, XLSX, MT940 ou CAMT.053, par REST. Elle lit le relevé et renvoie le fichier converti avec un aperçu du compte, de la période, des soldes et des premières opérations. Seule une conversion réussie est facturée. Les fichiers sont traités pour la requête, sans archive de documents.

Ce que fait l’API

  • POST /api/v1/bank/convert avec target égal à bank-csv, xlsx, mt940 ou camt-053.
  • Un fichier peut produire plusieurs fichiers de relevés. Si un choix ou une valeur manque, la réponse contient status: "need" ; renvoyez le même fichier, la réponse et resume. Une réponse need est gratuite ; une conversion terminée est facturée.
  • La sortie MT940 exige statementNumber dans la requête.
  • Le CSV utilise des colonnes fixes. Associez-les aux champs de votre importateur et vérifiez ses réglages de date et de décimale.

Ce qu’elle ne fait pas

Elle ne lit pas encore les relevés PDF et ne se connecte à aucune banque. La lecture des fichiers CAMT.053 et MT940 est en bêta. Il n’y a pas de sortie JSON : l’aperçu de la réponse est un résumé, pas le relevé complet.

Démarrage rapide

Chaque exemple fait le même appel. Avant publication, chacun est exécuté contre un serveur Klarbon local et le vrai moteur de validation.

Créez une clé sur la page de votre compte et placez-la dans KLARBON_API_KEY. Ne la mettez jamais dans l’adresse.

POST /api/v1/bank/convert

curl + jq
curl -sS https://klarbon.app/api/v1/bank/convert \
  -H "Authorization: Bearer $KLARBON_API_KEY" \
  -H "Idempotency-Key: statement-2026-11-04-csv" \
  -F "file=@statement.xml;type=application/xml" \
  -F target=bank-csv \
  -o result.json
jq -e '.ok' result.json > /dev/null || { jq -r '.error + ": " + .message' result.json; exit 1; }
jq -e '.status == "converted"' result.json > /dev/null || { jq -r '"Klarbon needs " + .need' result.json; exit 1; }
jq -r '.files[0].content' result.json | base64 --decode > "$(jq -r '.files[0].filename' result.json)"
TypeScript, Node.js 22.18+
import { readFile, writeFile } from "node:fs/promises"

type KlarbonFile = { content: string; filename: string; mime: string; bytes: number }
type Failure = { ok: false; error: string; message: string }
type Converted = { ok: true; status: "converted"; files: KlarbonFile[]; credits: { spent: number; balance: number } }
type Need = { ok: true; status: "need"; need: string; resume: string }

const form = new FormData()
form.append("file", new Blob([await readFile("statement.xml")], { type: "application/xml" }), "statement.xml")
form.append("target", "bank-csv")

const response = await fetch("https://klarbon.app/api/v1/bank/convert", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.KLARBON_API_KEY}`,
    "Idempotency-Key": "statement-2026-11-04-csv",
  },
  body: form,
})
const result = (await response.json()) as Converted | Need | Failure
if (!result.ok) throw new Error(`${response.status} ${result.error}: ${result.message}`)
if (result.status === "need") throw new Error(`Klarbon needs ${result.need}: send it with resume`)
for (const file of result.files) await writeFile(file.filename, Buffer.from(file.content, "base64"))
console.log(`${result.files.length} file(s) written, ${result.credits.balance} credits left`)
Python 3.9+, requests
import base64
import os

import requests

with open("statement.xml", "rb") as upload:
    response = requests.post(
        "https://klarbon.app/api/v1/bank/convert",
        headers={
            "Authorization": f"Bearer {os.environ['KLARBON_API_KEY']}",
            "Idempotency-Key": "statement-2026-11-04-csv",
        },
        files={"file": ("statement.xml", upload, "application/xml")},
        data={"target": "bank-csv"},
        timeout=120,
    )
result = response.json()
if not result["ok"]:
    raise SystemExit(f"{response.status_code} {result['error']}: {result['message']}")
if result["status"] == "need":
    raise SystemExit(f"Klarbon needs {result['need']}: send it with resume")
for written in result["files"]:
    with open(written["filename"], "wb") as output:
        output.write(base64.b64decode(written["content"]))
print(len(result["files"]), "file(s) written,", result["credits"]["balance"], "credits left")
PHP 8+, curl
<?php
$curl = curl_init('https://klarbon.app/api/v1/bank/convert');
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 120,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('KLARBON_API_KEY'),
        'Idempotency-Key: statement-2026-11-04-csv',
    ],
    CURLOPT_POSTFIELDS => [
        'file' => new CURLFile('statement.xml', 'application/xml', 'statement.xml'),
        'target' => 'bank-csv',
    ],
]);
$body = curl_exec($curl);
if ($body === false) {
    fwrite(STDERR, curl_error($curl) . "\n");
    exit(1);
}
$result = json_decode($body, true);
if (!$result['ok']) {
    $status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
    fwrite(STDERR, "$status {$result['error']}: {$result['message']}\n");
    exit(1);
}
if ($result['status'] === 'need') {
    fwrite(STDERR, "Klarbon needs {$result['need']}: send it with resume\n");
    exit(1);
}
foreach ($result['files'] as $written) {
    file_put_contents($written['filename'], base64_decode($written['content']));
}
echo count($result['files']) . " file(s) written, {$result['credits']['balance']} credits left\n";
C#, .NET 10
using System.Net.Http.Headers;
using System.Text.Json;

using var http = new HttpClient();
var key = Environment.GetEnvironmentVariable("KLARBON_API_KEY");
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", key);

var upload = new ByteArrayContent(await File.ReadAllBytesAsync("statement.xml"));
upload.Headers.ContentType = new MediaTypeHeaderValue("application/xml");

using var request = new HttpRequestMessage(HttpMethod.Post, "https://klarbon.app/api/v1/bank/convert?target=bank-csv") { Content = upload };
request.Headers.Add("Idempotency-Key", "statement-2026-11-04-csv");
using var response = await http.SendAsync(request);
using var json = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
var result = json.RootElement;
if (!result.GetProperty("ok").GetBoolean())
{
    Console.Error.WriteLine($"{(int)response.StatusCode} {result.GetProperty("error")}: {result.GetProperty("message")}");
    return 1;
}
if (result.GetProperty("status").GetString() == "need")
{
    Console.Error.WriteLine($"Klarbon needs {result.GetProperty("need")}: send it with resume");
    return 1;
}
foreach (var written in result.GetProperty("files").EnumerateArray())
{
    await File.WriteAllBytesAsync(written.GetProperty("filename").GetString()!,
        Convert.FromBase64String(written.GetProperty("content").GetString()!));
}
Console.WriteLine($"{result.GetProperty("files").GetArrayLength()} file(s) written, {result.GetProperty("credits").GetProperty("balance")} credits left");
return 0;

La réponse

La réponse à l’appel curl ci-dessus, enregistrée lors de cette exécution avec Klarbon synthetic fixture, CC0-1.0.

Raccourci pour la page: files[0].content: base64 cut

{
  "ok": true,
  "status": "converted",
  "format": "camt-053",
  "files": [
    {
      "content": "77u/IkJvb2tpbmcgZGF0ZSI7IlZhbHVlIGRhdGUiOyJBbW91...",
      "filename": "statement.csv",
      "mime": "text/csv;charset=utf-8",
      "bytes": 300
    }
  ],
  "preview": {
    "bank": null,
    "accountHolder": null,
    "iban": "DE89370400440532013000",
    "currency": "EUR",
    "period": {
      "from": "2026-11-02",
      "to": "2026-11-04"
    },
    "openingBalance": "1000.00",
    "closingBalance": "1075.00",
    "transactionCount": 2,
    "firstTransactions": [
      {
        "bookingDate": "2026-11-02",
        "valueDate": "2026-11-02",
        "amount": "100.00",
        "description": "Fictional customer payment",
        "reference": "TEST-1"
      },
      {
        "bookingDate": "2026-11-03",
        "valueDate": "2026-11-03",
        "amount": "-25.00",
        "description": "Fictional office supplies",
        "reference": "TEST-2"
      }
    ],
    "reconciliation": {
      "ok": true,
      "difference": "0.00",
      "checkedBalances": 1
    },
    "balanceSource": {
      "opening": "printed",
      "closing": "printed"
    }
  },
  "warnings": [],
  "credits": {
    "spent": 1,
    "balance": 196,
    "plan": 0,
    "bought": 196
  }
}

Tarifs

Des packs API prépayés, achetés par carte sur la page de votre compte : 1 000 appels pour 39,00 €, 5 000 appels pour 129,00 €, 25 000 appels pour 449,00 €, 100 000 appels pour 990,00 €, sans date d’expiration. Votre première clé apporte 25 appels gratuits. Les appels payants consomment d’abord le solde API, puis les mêmes crédits que le site. Un appel qui échoue ne coûte rien.

Appel Coût
POST /open Gratuit, usage raisonnable jusqu’à 1 000 par jour et par compte
POST /check Gratuit dans la limite quotidienne de votre offre (20 par jour avec l’offre gratuite)
POST /convert, POST /make 1 appel, seulement si le fichier produit est valide
POST /bank/convert 1 appel par tranche entamée de 500 opérations, seulement après conversion

Limites

  • Fichiers jusqu’à 20 Mo, PDF jusqu’à 50 pages.
  • 60 requêtes par minute et par clé, 120 par compte. Une réponse 429 indique Retry-After.
  • Jusqu’à 10 clés par compte. Idempotency-Key est respecté pendant 24 heures : une nouvelle tentative n’est jamais facturée deux fois.

Erreurs

Chaque erreur a la forme { ok: false, error, message } : un code stable et une phrase claire.

Statut Code Quand
401 auth Aucune clé, ou une clé inconnue ou révoquée.
402 no_credits Solde API et crédits tous deux insuffisants. Rien n’a été fait ; topUpUrl indique où en acheter.
413 too_large Plus de 20 Mo ou de 50 pages PDF.
415 unsupported Un format de fichier que la route n’accepte pas.
422 invalid Le fichier est illisible, ou le fichier produit n’est pas valide. Non facturé.
429 limit Une limite de débit, ou les appels gratuits du jour.
503 engine_unavailable La validation est brièvement indisponible. Non facturé.

Confidentialité

Les fichiers sont traités pour la requête, sans archive de documents. Les journaux de l'application Klarbon ne contiennent ni nom de fichier, ni contenu, ni clé. La clé complète n'est pas conservée, seulement son empreinte HMAC et un court préfixe d'affichage.

Pour aller plus loin

La documentation pour les développeurs est en anglais.

Questions fréquentes

Quels formats de relevé l’API lit-elle ?

CAMT.053 et MT940, ainsi que d’autres formats structurés en bêta. La lecture de relevés PDF n’est pas encore disponible.

Vers quels formats peut-elle convertir ?

CSV, XLSX, MT940 et CAMT.053, ainsi que les sorties bêta prises en charge. Le paramètre target choisit un format par appel ; la réponse peut contenir plusieurs fichiers de relevés.

Que se passe-t-il si le fichier contient plusieurs relevés ?

L’API peut renvoyer un fichier par relevé. Si un choix de compte ou une donnée manque, elle répond status need. Renvoyez le même fichier, la réponse et resume. Une réponse need est gratuite ; une conversion terminée est facturée.

L’API se connecte-t-elle à ma banque ?

Non. Vous envoyez un fichier que votre banque a déjà exporté. Klarbon ne demande jamais d’identifiants bancaires.

Sources

Mis à jour le 5 novembre 2026