M2M-Kochbuch - Server-zu-Server-API-Keys.
Serverseitiger API-Zugriff nutzt ak_-Praefix-Keys aus api-keys-admin.html. Jeder Aufruf traegt Authorization: Bearer ak_... ueber TLS, wird pro Mandant ratenbegrenzt und laesst sich per Klick in der Admin-UI widerrufen. Mandanten mit European Digital Identity Wallet-Anmeldung nutzen dieselbe Key-Oberflaeche fuer Hintergrundjobs.
Framework-Matrix (Weg A - API-Keys)
| Framework / Sprache | Bibliothek | Rezept | Snippet |
|---|---|---|---|
| Node.js | axios | Anzeigen | m2m-api-key-nodejs.js |
| Python | requests | Anzeigen | m2m-api-key-python.py |
| PHP | curl | Anzeigen | m2m-api-key-php.php |
| cURL | plain shell | Anzeigen | m2m-api-key-curl.sh |
| Java | java.net.http | Anzeigen | m2m-api-key-java.java |
| Go | net/http | Anzeigen | m2m-api-key-go.go |
| .NET | HttpClient | Anzeigen | m2m-api-key-dotnet.cs |
Node.js Rezept
axios. Rohdatei laden .js
// Server-to-server call to a CodeB tenant using an API key.
// European Digital Identity Wallet claims presented at sign-in are
// out-of-band from M2M; API keys are for background jobs.
// [m2m-cookbook 2026-07-23]
// npm install axios
//
// Mint the key at https://<CODEB_TENANT_HOST>/api-keys-admin.html
// Keys have the form ak_XXXXXXXXXXXXXXXX and MUST travel over TLS.
const axios = require('axios');
const TENANT = 'https://<CODEB_TENANT_HOST>';
const API_KEY = process.env.CODEB_API_KEY; // ak_...
const api = axios.create({
baseURL: TENANT,
timeout: 15000,
headers: { Authorization: 'Bearer ' + API_KEY }
});
async function listUsers(){
const r = await api.get('/api.ashx?action=users.list');
return r.data;
}
listUsers().then(u => console.log(u.length + ' users'));
Python Rezept
requests. Rohdatei laden .python
# Server-to-server call to a CodeB tenant using an API key.
# European Digital Identity Wallet claims presented at sign-in are
# out-of-band from M2M; API keys are for background jobs.
# [m2m-cookbook 2026-07-23]
# pip install requests
#
# Mint the key at https://<CODEB_TENANT_HOST>/api-keys-admin.html
# Keys have the form ak_XXXXXXXXXXXXXXXX and MUST travel over TLS.
import os, requests
TENANT = "https://<CODEB_TENANT_HOST>"
API_KEY = os.environ["CODEB_API_KEY"] # ak_...
sess = requests.Session()
sess.headers["Authorization"] = f"Bearer {API_KEY}"
def list_users():
r = sess.get(f"{TENANT}/api.ashx?action=users.list", timeout=15)
r.raise_for_status()
return r.json()
if __name__ == "__main__":
print(len(list_users()), "users")
PHP Rezept
curl. Rohdatei laden .php
<?php
// Server-to-server call to a CodeB tenant using an API key.
// European Digital Identity Wallet claims are out-of-band; API keys are
// for background jobs.
// [m2m-cookbook 2026-07-23]
//
// Mint the key at https://<CODEB_TENANT_HOST>/api-keys-admin.html
// Keys have the form ak_XXXXXXXXXXXXXXXX and MUST travel over TLS.
const TENANT = 'https://<CODEB_TENANT_HOST>';
$apiKey = getenv('CODEB_API_KEY'); // ak_...
function api_get(string $path, string $apiKey): array {
$ch = curl_init(TENANT . $path);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
CURLOPT_TIMEOUT => 15,
]);
$body = curl_exec($ch);
if ($body === false) throw new RuntimeException(curl_error($ch));
return json_decode($body, true);
}
$users = api_get('/api.ashx?action=users.list', $apiKey);
printf("%d users\n", count($users));
cURL Rezept
plain shell. Rohdatei laden .bash
#!/usr/bin/env bash
# Server-to-server call to a CodeB tenant using an API key.
# European Digital Identity Wallet claims are out-of-band; API keys are
# for background jobs.
# [m2m-cookbook 2026-07-23]
#
# Mint the key at https://<CODEB_TENANT_HOST>/api-keys-admin.html
# Keys have the form ak_XXXXXXXXXXXXXXXX and MUST travel over TLS.
set -euo pipefail
TENANT="${CODEB_TENANT:-https://<CODEB_TENANT_HOST>}"
API_KEY="${CODEB_API_KEY:?set CODEB_API_KEY=ak_...}"
curl -sSf \
-H "Authorization: Bearer ${API_KEY}" \
"${TENANT}/api.ashx?action=users.list" | jq .
Java Rezept
java.net.http. Rohdatei laden .java
// Server-to-server call to a CodeB tenant using an API key.
// European Digital Identity Wallet claims are out-of-band; API keys are
// for background jobs.
// [m2m-cookbook 2026-07-23]
//
// Mint the key at https://<CODEB_TENANT_HOST>/api-keys-admin.html
// Keys have the form ak_XXXXXXXXXXXXXXXX and MUST travel over TLS.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class CodebApiKeyClient {
private static final String TENANT = "https://<CODEB_TENANT_HOST>";
private static final String API_KEY = System.getenv("CODEB_API_KEY");
public static void main(String[] args) throws Exception {
HttpClient c = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10)).build();
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(TENANT + "/api.ashx?action=users.list"))
.header("Authorization", "Bearer " + API_KEY)
.timeout(Duration.ofSeconds(15))
.GET().build();
HttpResponse<String> r = c.send(req, HttpResponse.BodyHandlers.ofString());
if (r.statusCode() != 200) throw new RuntimeException("HTTP " + r.statusCode());
System.out.println(r.body());
}
}
Go Rezept
net/http. Rohdatei laden .go
// Server-to-server call to a CodeB tenant using an API key.
// European Digital Identity Wallet claims are out-of-band; API keys are
// for background jobs.
// [m2m-cookbook 2026-07-23]
//
// Mint the key at https://<CODEB_TENANT_HOST>/api-keys-admin.html
// Keys have the form ak_XXXXXXXXXXXXXXXX and MUST travel over TLS.
package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
const Tenant = "https://<CODEB_TENANT_HOST>"
func main() {
apiKey := os.Getenv("CODEB_API_KEY")
if apiKey == "" {
fmt.Fprintln(os.Stderr, "set CODEB_API_KEY=ak_...")
os.Exit(1)
}
client := &http.Client{Timeout: 15 * time.Second}
req, _ := http.NewRequest("GET", Tenant+"/api.ashx?action=users.list", nil)
req.Header.Set("Authorization", "Bearer "+apiKey)
resp, err := client.Do(req)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
.NET Rezept
HttpClient. Rohdatei laden .csharp
// Server-to-server call to a CodeB tenant using an API key.
// European Digital Identity Wallet claims are out-of-band; API keys are
// for background jobs.
// [m2m-cookbook 2026-07-23]
//
// Mint the key at https://<CODEB_TENANT_HOST>/api-keys-admin.html
// Keys have the form ak_XXXXXXXXXXXXXXXX and MUST travel over TLS.
using System.Net.Http.Headers;
const string Tenant = "https://<CODEB_TENANT_HOST>";
string apiKey = Environment.GetEnvironmentVariable("CODEB_API_KEY")
?? throw new InvalidOperationException("set CODEB_API_KEY=ak_...");
using var http = new HttpClient { BaseAddress = new Uri(Tenant),
Timeout = TimeSpan.FromSeconds(15) };
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", apiKey);
var body = await http.GetStringAsync("/api.ashx?action=users.list");
Console.WriteLine(body);
Selber testen
Roundtrip-Test: curl -sSf -H 'Authorization: Bearer ak_...' https://<host>/api.ashx?action=ping. Nicht-200-Antworten enthalten error-Code und lesbaren hint-Text.
Sicherheitshinweise
- Keys ausschliesslich per TLS. Klartextkanaele werden abgelehnt.
- Ratenbegrenzung pro Mandant: HTTP 429 mit
Retry-After-Header - Backoff und fortsetzen. - Rotation manuell in api-keys-admin.html; Widerruf sofort (In-Memory-Cache in einem Heartbeat verworfen).
- Jeder Request-Pfad meldet Anomalien und Integritaetspruefungen mit lauten Diagnosen; einen Key nicht mitten im Aufruf loeschen, wenn kein 401 gewuenscht ist.
FAQ
Strukturierte Antworten im obigen Schema-Block.