Overview
Base URL: https://api.ckonto.de
Version: v1 (all endpoints start with /v1/)
Format: JSON (Content-Type: application/json)
Discovery: /service | OpenAPI 3.0 Schema
Authentication
All endpoints (except /service, /service/openapi.json, and /v1/ping//v1/test) require a valid API key as a bearer token:
Authorization: Bearer API_KEY
Alternatively via the X-API-Key: API_KEY header. The key is passed exclusively via header - not as a query parameter and not in the request body. This keeps it out of server logs, browser histories, and Referer headers.
/v1/ping and /v1/test are deliberately reachable without authentication (intended for health checks/monitoring). A token sent anyway is ignored and not checked.
You can get an API key via ckonto.de/bestellung.htm.
401 invalid_key back - even if the request also uses the wrong HTTP method, a malformed path, or missing parameters (which would otherwise return 405 method_not_allowed or 400). With a valid key, the respective structural error is reported as documented. Endpoints
Check account number / bank code
Checks a German account number and bank code (BLZ). Optionally with IBAN generation (sepa=1).
Example GET
curl -H "Authorization: Bearer API_KEY" \
"https://api.ckonto.de/v1/kto/0532013000/37040044"
Example POST
curl -H "Authorization: Bearer API_KEY" \
-H "Content-Type: application/json" \
-d '{"kontonummer":"0532013000","bankleitzahl":"37040044"}' \
"https://api.ckonto.de/v1/kto"
Response
{
"status": 1,
"message": "The bank account details are valid",
"data": {
"iban": null,
"bic": null,
"kto": "0532013000",
"blz": "37040044",
"bank": "Commerzbank",
"zip": "50447",
"location": "Köln",
"country": "DE"
}
}
With sepa=1 (GET: query parameter, POST: in the JSON body), iban and bic are also returned. Only 0 and 1 are allowed; other values return HTTP 400 with code invalid_sepa. If the parameter is missing, the default 0 applies.
country always contains the ISO 3166-1 alpha-2 country code of the bank (e.g. DE), not the spelled-out country name. If no code can be determined, the field is an empty string.
ccd (optional, GET: query parameter, POST: in the JSON body): a 2-letter country code that controls IBAN generation from account number/bank code for countries outside Germany. Supported: DE, AT, CH, BE, CZ, SK, ES (case-insensitive, other values are ignored). Affects the response field country independently of sepa.
Important: kontonummer and bankleitzahl must be in the country-specific format - not necessarily 8 digits like a German bank code. ccd alone only sets country - for the generated iban/bic, also set sepa=1. Example for Slovakia:
curl -H "Authorization: Bearer API_KEY" \
"https://api.ckonto.de/v1/kto/5207004203041425/8360?ccd=SK&sepa=1"
{
"status": 1,
"message": "The bank account details are valid",
"data": {
"iban": "SK4283605207004203041425",
"bic": "BREXSKBXXXX",
"kto": "5207004203041425",
"blz": "8360",
"bank": "mBank S.A., pobočka zahraničnej banky",
"zip": "SK-81109",
"location": "Bratislava",
"country": "SK"
}
}
Check IBAN
Checks an IBAN (international, focus on DE/AT/CH/EU). Optionally with BIC validation. Also available as a batch of up to 500 IBANs via POST.
iban and bic are always returned by this endpoint - a sepa parameter is syntactically accepted here but has no effect (unlike the account number/bank code check, where sepa=1 is required to enable it).
Example GET
curl -H "Authorization: Bearer API_KEY" \
"https://api.ckonto.de/v1/iban/DE89370400440532013000"
Response (single check)
{
"status": 1,
"message": "The IBAN is valid",
"data": {
"iban": "DE89370400440532013000",
"bic": "COBADEFFXXX",
"kto": "0532013000",
"blz": "37040044",
"bank": "Commerzbank",
"zip": "DE-50447",
"location": "Köln",
"country": "DE",
"sepa_methods": {
"sct": 1,
"sdd": 1,
"b2b": 1,
"scc": 1
}
}
}
sepa_methods shows which SEPA payment methods the bank supports: sct (credit transfer), sdd (direct debit), b2b (business-to-business direct debit), scc (cards clearing). Value 1 = supported, 0 = not supported, 9 = cannot be determined (incomplete bank master data for this country, mostly occurs outside DE/AT/CH).
country always contains the ISO 3166-1 alpha-2 country code of the bank (e.g. DE, AT, CH), not the spelled-out country name. If no code can be determined, the field is an empty string.
Example POST – single check with BIC
curl -H "Authorization: Bearer API_KEY" \
-H "Content-Type: application/json" \
-d '{"iban":"DE89370400440532013000","bic":"COBADEFFXXX"}' \
"https://api.ckonto.de/v1/iban"
Negative examples (each a different status/error)
| IBAN | Result | Reason |
|---|---|---|
DE00370400440532013000 | HTTP 200, status: 0 | Incorrect IBAN check digit (otherwise identical to the valid example above) |
DE93999999990000000001 | HTTP 200, status: 7 | Bank code (BLZ) does not exist |
XX | HTTP 400, invalid_iban | Format error - too short / not a valid country prefix |
The first two cases are not errors in the HTTP sense (HTTP 200) - the request was syntactically correct, the business check result is "invalid" or "bank code unknown" respectively. Only the third case is a genuine request error (HTTP 400), because the IBAN does not even match the basic format.
Example POST – batch (up to 500 IBANs)
curl -H "Authorization: Bearer API_KEY" \
-H "Content-Type: application/json" \
-d '{"ibans":["DE89370400440532013000","AT001234512345678901"]}' \
"https://api.ckonto.de/v1/iban"
Batch response
Counting: every IBAN in a batch counts as one request - including entries that already fail the format check.
Every element in batch.results always contains iban, valid, status, and data - even if the IBAN is not valid from a business perspective (e.g. status: 7, "bank code does not exist"). This is not an error and carries no error object. An error object only appears if this item could not be checked at all (format error or backend failure); it has a flat structure and, like the other error objects, uses the field code (not error_code).
{
"status": 1,
"message": "Batch processing completed",
"batch": {
"total": 3,
"results": [
{ "status": 1, "iban": "DE89370400440532013000", "valid": true, "data": { "country": "DE", "sepa_methods": { "sct": 1, "sdd": 1, "b2b": 1, "scc": 1 }, ... } },
{ "status": 7, "iban": "DE93999999990000000001", "valid": false, "data": { "country": "DE", ... } },
{ "status": 0, "iban": "XX", "valid": false, "data": { "country": "", ... },
"error": { "code": "invalid_iban", "message": "The IBAN is invalid or has an incorrect format", "field": "iban" } }
]
}
}
Bank search
Searches banks by name, location, postal code, or bank code. At least one of the fields name, location, zip, or bankleitzahl must be set - without any search criterion, the API returns HTTP 400 with code missing_search_criteria. Maximum 50 results.
max limits the number of results (1-50). If max is missing, the default 10 applies. Values outside 1-50 or non-numeric values return HTTP 400 with code invalid_max.
max (i.e. the result list was truncated by max), status: 9 is returned instead of status: 1 - with an otherwise identical response structure (results.count/results.items still populated, HTTP 200). This is intentional behavior of the cKonto search and not an error; it merely indicates that further results, not included here, may exist. To get all results, increase max or narrow the search criteria (name, location, zip, bankleitzahl) further. name and location are AND-combined and are each matched as a substring (case-insensitive) against the bank master data. Example: location=Berlin also returns "Bernau bei Berlin" and "Überlingen", because both locations contain the substring "berlin". This is intentional behavior. name/location 3 characters, zip 2 characters, bankleitzahl 4 characters. This is not an HTTP error - a value that is too short still returns HTTP 200 with an empty result and the matching business error status (status: 2/3/4/8, see the business status table below). name and location only accept plain letters - no digit (not even combined with letters), no umlaut, no ß, no space. The vendor documentation describes the fields as "alphanumeric"; in practice, every digit is rejected regardless of position. A value that is too short or not allowed returns HTTP 200 with status: 3/4 instead of a result. Examples: location=Köln, name=Postbank1, and name=Deutsche Bank (multi-word) fail; location=Koeln and name=Deutsche work. This is a limitation of the cKonto search function itself, not an encoding issue in the wrapper. Example GET
curl -H "Authorization: Bearer API_KEY" \
"https://api.ckonto.de/v1/search?name=Sparkasse&location=Berlin&max=5"
Response
{
"status": 1,
"message": "The search was successful",
"results": {
"count": 4,
"items": [
{ "bic": "BELADEBEXXX", "blz": "10050000", "bank": "BSK 1818 - Berliner Sparkasse", "zip": "10889", "location": "Berlin" },
...
]
}
}
As everywhere else, status here is a numeric value (not a string).
Health check
Checks whether the service is reachable. /v1/test additionally indicates test mode. No bearer token required - both endpoints are deliberately reachable without authentication (health check/monitoring). A token sent anyway is ignored.
{ "status": 1, "message": "Pong" }
Errors
Errors are always returned as a JSON object with the key error. A complete list of all error codes with descriptions and examples can be found at /api/docs/en/errors.
{
"error": {
"http_status": 401,
"code": "invalid_key",
"message": "The API key is not valid"
}
}
status (0-9, see below); for API/HTTP errors, error.code and error.http_status. In both cases, message is English free text without any stability guarantee - for display only, do not use it in program logic. Business status codes
The status field in a success response contains the business check status from cKonto:
| Code | Meaning |
|---|---|
0 | Account number/IBAN not valid / no results for this search |
1 | Bank account details valid |
2 | Bank code (BLZ) must be 8 digits / invalid input: postal code |
3 | Invalid input: account number / invalid input: location |
4 | Errors in account number and bank code / invalid input: IBAN / invalid input: name |
7 | Bank code (BLZ) does not exist / invalid input: max |
8 | Demo mode / invalid input: bank code (BLZ) |
9 | Bank account details cannot be verified / output limit reached |
Response headers
| Header | Description |
|---|---|
X-Request-ID | Unique ID for the request - can be sent by the client and is mirrored back (only [A-Za-z0-9-], other characters are removed, truncated to 64 characters); otherwise generated server-side. For log correlation and debugging. |
X-RateLimit-Limit | Maximum requests per time window |
X-RateLimit-Window | Window size in seconds |
X-RateLimit-Policy | Rate limit policy as plain text, e.g. "60 requests per 10 seconds". The limit is not applied per API key. |
X-Idempotency-Key | Mirrored back if sent by the client (truncated to 64 characters). Purely a correlation value - no server-side deduplication takes place; a repeated POST with the same key is processed in full again. |
X-Request-ID header in the request (e.g. a UUID) so you can uniquely track your requests in logs.