Sign in
Einführung/Authentifizierung

Authentifizierung & Anfrage-Signierung

Signieren Sie API-Anfragen mit HMAC-SHA256 unter Verwendung Ihrer Projekt-UUID und Ihres API-Schlüssels.

Jede API-Anfrage (mit Ausnahme eingehender Webhooks) muss Ihre Projekt-UUID und eine Anfrage-Signatur enthalten. Die Signatur belegt, dass die Anfrage von Ihnen stammt und unterwegs nicht verändert wurde.

API-Schlüssel

2328.io verwendet zwei Schlüssel, die denselben Signieralgorithmus nutzen, aber unterschiedliche Endpoints abdecken:

SchlüsselVerwendet für
API keyZahlungen, statische Wallets, Guthaben, Wechselkurse sowie Verifizierung von Zahlungs- und Static-Wallet-Webhooks
Payout API keyAlle /v1/payout/*-Endpoints und Verifizierung von Payout-Webhooks

Beide Schlüssel finden Sie in den Projekteinstellungen unter 2328.io. Die Beispiele unten sprechen generisch von "API key" — verwenden Sie jeweils den richtigen Schlüssel für den aufgerufenen Endpoint.

Vermischen Sie die beiden Schlüssel niemals: Eine Auszahlungsanfrage mit dem regulären API-Schlüssel zu signieren (oder eine Zahlungsanfrage mit dem Payout-Schlüssel) führt zu einem Signaturfehler.

Erforderliche Header

HeaderTypPflichtBeschreibung
Content-TypestringjaImmer application/json
projectstringjaIhre Projekt-UUID
signstringjaHMAC-SHA256-Signatur der Anfrage, berechnet mit Ihrem API-Schlüssel
User-AgentstringjaIdentifiziert Ihre Anwendung (z. B. MyShop/1.4 (+https://myshop.example)). Anfragen ohne User-Agent können blockiert werden.

So funktioniert die Signatur

Stellen Sie sich die Signatur als Fingerabdruck des Anfrage-Bodys vor. Sie wird wie folgt erstellt:

  1. Body in JSON serialisieren (kompakt — ohne zusätzliche Whitespaces).
  2. Dieses JSON in base64 codieren. Dieser Schritt normalisiert die Eingabe sprachübergreifend — sobald es sich um reines ASCII handelt, erzeugt jede Sprache dieselben Bytes für HMAC.
  3. HMAC-SHA256 des Base64-Strings mit Ihrem API-Schlüssel berechnen und das Ergebnis in hex (Kleinbuchstaben) umwandeln.

Für GET und andere Anfragetypen ohne Body signieren Sie stattdessen einen leeren String anstelle des JSON.

Die Signatur des leeren Strings ist für einen gegebenen API-Schlüssel konstant. Sie können sie zwischenspeichern, wenn Sie viele GET-Aufrufe ausführen.

Implementierungen

PHP
<?php
function apiSign(array $data, string $apiKey): string {
    $json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    $base64 = base64_encode($json);
    return hash_hmac('sha256', $base64, $apiKey);
}

Anfragen ohne Body (GET)

Für Anfragen mit leerem Body (z. B. GET /v1/payout/status/{uuid}) signieren Sie einen leeren String:

Shell
SIGN=$(printf '' | openssl dgst -sha256 -hmac "$API_KEY" -hex | awk '{print $NF}')

Vollständiges Anfragebeispiel

Shell
curl -X POST https://api.2328.io/api/v1/payment \
  -H "Content-Type: application/json" \
  -H "User-Agent: MyShop/1.0 (+https://myshop.example)" \
  -H "project: YOUR_PROJECT_UUID" \
  -H "sign: YOUR_HMAC_SIGNATURE" \
  -d '{"amount":"100.00","currency":"USD","order_id":"ORDER-123"}'

Geben Sie Ihren API-Schlüssel niemals in clientseitigem Code preis. Signieren Sie Anfragen auf Ihrem Backend. Ein durchgesickerter API-Schlüssel verschafft jedem vollen Zugriff auf Ihr Händlerkonto.

Webhook-Signaturen verifizieren

Wenn 2328.io einen Webhook an Sie sendet, läuft derselbe Algorithmus rückwärts ab:

  1. Ziehen Sie das Feld sign aus dem payload.
  2. JSON-codieren Sie die übrigen Felder (kompakt, ohne Whitespace).
  3. Codieren Sie diesen String in base64.
  4. Berechnen Sie HMAC-SHA256 mit dem passenden Schlüssel.
  5. Vergleichen Sie das Ergebnis mit der erhaltenen sign mittels eines konstantzeitigen Vergleichs (hash_equals, crypto.timingSafeEqual, hmac.compare_digest, subtle.ConstantTimeCompare, OpenSSL.fixed_length_secure_compare).

Der Signierschlüssel hängt von der Webhook-Quelle ab:

WebhookSchlüssel zur Verifizierung
Zahlungs- / Static-Wallet-Webhooks (/v1/payment, /v1/static-wallet)API key
Payout-Webhooks (/v1/payout)Payout API key

Häufige Verifizierungsfehler. Ihr JSON-Encoder muss exakt dieselben Bytes erzeugen wie der Absender — andernfalls unterscheidet sich das Base64 und die Signatur passt nicht.

  • Go: Verwenden Sie json.NewEncoder mit SetEscapeHTML(false). Das Standard-json.Marshal escaped <, >, & zu < und zerstört die Signatur.
  • Python: Übergeben Sie ensure_ascii=False an json.dumps. Ohne dies werden Nicht-ASCII-Zeichen (Kyrillisch, Chinesisch, …) zu \uXXXX escaped.
  • Kompaktes JSON: keine Leerzeichen zwischen den Feldern (separators=(",", ":") in Python).
  • Feldreihenfolge (Go): Ein einfaches map[string]any randomisiert die Schlüssel beim erneuten Kodieren. Verwenden Sie json.RawMessage, ein geordnetes struct oder entfernen Sie sign aus den Rohbytes.

Wenn die Verifizierung weiterhin fehlschlägt, führen Sie apiSign selbst auf dem Payload aus — es muss dieselbe Hex-Zeichenkette erzeugen wie das empfangene sign.

Eine gültige Signatur verhindert keine Replays. Sie beweist nur, dass der Webhook von 2328.io stammt — sie verhindert nicht, dass ein Angreifer einen abgefangenen Webhook später erneut postet. Prüfen Sie immer die Idempotenz per uuid (oder txid bei statischen Wallets), bevor Sie Geldmittel gutschreiben. Lehnen Sie mit HTTP 401 ab, wenn die Signatur fehlt oder falsch ist.

Vollständige Codebeispiele finden Sie auf Webhook Notifications. Wiederholungsverhalten und Idempotenzregeln stehen in Best Practices.