API-Dokumentation
Cryptanio mit Ihrer Anwendung verbinden.
Vertrag v1 / 1.0.0 62 / 2026-10-10
Inhalt
Erste Schritte
API für Ihren Server. Zuerst Projekte, Dienste und Adresspools in Account konfigurieren; API führt darin schlüsselberechtigte Aktionen aus.
- Konto verifizieren und benötigten Dienst unter Meine Dienste aktivieren.
- Einen API-Schlüssel mit minimalen Berechtigungen erstellen und auf Ihrem Server aufbewahren.
- Wählen Sie Ihre Aufgabe: Adresse überwachen, Rechnung erstellen oder Ereignisse empfangen.
Beispiele führen echte Aktionen mit Live-Daten aus. Objekte erstellen oder löschen kann Dienstquoten verbrauchen. Schlüssel werden nie eingebettet, sondern aus Umgebungsvariablen gelesen.
Anweisungen für Ihren Agenten
Anweisung in Agentenchat oder Projektregeln einfügen. Sie hilft dem Agenten, Dienste, Preise und Referenz zu verstehen und dann eine REST-API- oder SDK-Integration zu schreiben. Der Agent kann in Ihrer Sprache antworten.
Learn how to integrate a server-side application with Cryptanio's public REST API before proposing or writing integration code.
Start here:
- Website: https://cryptanio.com/
- Documentation index: https://cryptanio.com/llms.txt
- Product, services and pricing: https://cryptanio.com/cryptanio.md
- API integration index: https://cryptanio.com/docs/llms.txt
- API guide: https://cryptanio.com/docs.md
- Exact API v1 contract: https://cryptanio.com/openapi.json
- FAQ: https://cryptanio.com/faq/index.md
- SDK setup and examples: https://cryptanio.com/docs.html#sdk
Read the relevant method reference before using it. Use the public API at https://api.cryptanio.com/v1. Do not assume a public sandbox exists.
Use HTTP requests or the documented SDK for the application's language. Match request fields, response schemas and errors to OpenAPI; do not invent endpoints or SDK methods.
Check the actual enabled networks, service, project and API key permissions. Product documentation is not evidence of a live payment, balance or deployment.
Keep API keys in the user's server environment or secret store. Never ask the user to paste a key into chat or put it in a URL, browser bundle or log.
Default to reading. Create, change or delete objects only when the user authorizes the specific task. Explain quota or billing consequences before a write.
Follow the documented confirmation, webhook verification, pagination and retry rules. Reuse an invoice's original Idempotency-Key and request when retrying.
Show the returned chain, asset, address, amount and expiry. Preserve payment_route.kind and its exact string value: destination_tag, memo, comment or reference is mandatory when present. The merchant order reference is a separate field.
For a payment QR use the returned payment_uri when present. A Solana Pay reference is not a wallet memo; do not rebuild its URI or replace it with a plain address. Offer the exact returned checkout_url only to the payer; never construct a checkout URL from an invoice ID. Neither a checkout redirect nor a QR scan confirms payment.
Distinguish pending, confirmed, rolled-back and simulated data. If a fact is unavailable, say so instead of guessing.
Answer the user's questions in their language. If a necessary product decision is not documented, ask instead of inventing it.Dieser Block enthält keine Schlüssel oder Kontodaten. API-Schlüssel mit minimalen Integrationsrechten nutzen und auf Anwendungsserver halten. Schlüssel nicht im Agentenchat teilen.
API-Referenz
Methoden: 16
Monitoring-Überwachungen
Ereignisse
Rechnungen
Webhook
API-Zustand
Netzwerke
Authentifizierung
Authorization: Bearer <API_KEY> von Ihrem Server senden. In Account → API-Schlüssel einen Schlüssel für Live-Daten erstellen, begrenzt auf benötigte Projekte und Aktionen. Derzeit keine öffentliche Sandbox.
Ein Schlüssel kann Lesezugriff, ausgewählte Aktionen, ein Projekt oder einen Dienst und bestimmte IP/CIDR-Bereiche erlauben. Ablauf, Pause und Widerruf beeinflussen ebenfalls den Zugriff. Zur Rotation einen Ersatzschlüssel mit passenden Beschränkungen erstellen, die Integration umstellen und den alten Schlüssel widerrufen. Schlüssel niemals in Browsercode, mobilen Apps oder URLs einbetten.
| Geltungsbereich | Zweck |
|---|---|
watches | Monitoring |
events | Ereignisse und Zahlungen |
invoices | Payments-Rechnungen |
webhooks | Webhook-Endpunkte |
stream | SSE |
Beschränkungen gelten gemeinsam, nicht alternativ. 401 bedeutet Schlüssel nicht akzeptiert; 403 kann fehlende Rechte oder unzulässige IP bedeuten. Unzugängliche Ressourcen können 404 liefern. Siehe Fehler und Wiederholungen.
SDK: einsatzbereite Clients
Datei für Ihre Sprache herunterladen, auf dem Anwendungsserver speichern und dem Konstruktor Ihren Schlüssel übergeben. Jeder Client deckt alle 16 Methoden dieser Referenz ab. Es gibt kein npm-, PyPI-, Composer- oder crates.io-Paket: Die heruntergeladenen Dateien sind das SDK.
| Sprache | Anforderungen | Datei |
|---|---|---|
| Node.js | Node.js 18+ | cryptanio.mjs |
| Python | Python 3.10+ | cryptanio.py |
| PHP | PHP 8.1+ / cURL | Cryptanio.php |
| Go | Go 1.22+ | cryptanio.go |
| Rust | Rust 2021 / reqwest 0.12 / serde_json 1 | cryptanio.rs |
Dateien teilen Release 1.0.0 62. Das Manifest enthält Version, Vertrag und SHA-256 jeder Datei. Zuerst CRYPTANIO_API_KEY und CRYPTANIO_PROJECT_ID in Umgebung setzen. Beispiele lesen nur Ereignisse, greifen aber auf Live-Kontodaten zu.
Node.js
Beispiel als .mjs neben cryptanio.mjs speichern.
import { Cryptanio } from './cryptanio.mjs';
const key = process.env.CRYPTANIO_API_KEY;
const project = process.env.CRYPTANIO_PROJECT_ID;
if (!key || !project) throw new Error('Set API key and project ID');
const api = new Cryptanio(key);
const page = await api.listEvents({ project, limit: 25 });
console.log(page);Um die Zahlungsdaten einer bestehenden Rechnung zu lesen, tragen Sie ihre ID in CRYPTANIO_RESOURCE_ID ein. Das Beispiel erhält das erforderliche payment_route, das zurückgegebene payment_uri für den QR-Code und das genaue checkout_url. Übergeben Sie das Ergebnis dem Zahler über Ihre Oberfläche, nicht über öffentliche Protokolle. Beträge bleiben Zeichenketten, fehlende Felder werden ausgelassen.
import { Cryptanio } from './cryptanio.mjs';
const key = process.env.CRYPTANIO_API_KEY;
const invoiceID = process.env.CRYPTANIO_RESOURCE_ID;
if (!key || !invoiceID) throw new Error('Set API key and invoice ID');
const api = new Cryptanio(key);
const invoice = await api.getInvoice(invoiceID);
const payment = {
chain: invoice.chain, asset: invoice.asset, address: invoice.address,
amount: invoice.amount, expires_at: invoice.expires_at,
payment_route: invoice.payment_route,
payment_uri: invoice.payment_uri, checkout_url: invoice.checkout_url,
};
console.log(JSON.stringify(payment, null, 2));Python
Beispiel als .py neben cryptanio.py speichern.
import os
from cryptanio import Cryptanio
api = Cryptanio(os.environ['CRYPTANIO_API_KEY'])
page = api.list_events({
'project': os.environ['CRYPTANIO_PROJECT_ID'], 'limit': 25
})
print(page)Um die Zahlungsdaten einer bestehenden Rechnung zu lesen, tragen Sie ihre ID in CRYPTANIO_RESOURCE_ID ein. Das Beispiel erhält das erforderliche payment_route, das zurückgegebene payment_uri für den QR-Code und das genaue checkout_url. Übergeben Sie das Ergebnis dem Zahler über Ihre Oberfläche, nicht über öffentliche Protokolle. Beträge bleiben Zeichenketten, fehlende Felder werden ausgelassen.
import json
import os
from cryptanio import Cryptanio
api = Cryptanio(os.environ['CRYPTANIO_API_KEY'])
invoice = api.get_invoice(os.environ['CRYPTANIO_RESOURCE_ID'])
payment = {field: invoice[field] for field in (
'chain', 'asset', 'address', 'amount', 'expires_at',
'payment_route', 'payment_uri', 'checkout_url'
) if field in invoice}
print(json.dumps(payment, ensure_ascii=False))PHP
Beispiel als .php neben Cryptanio.php speichern; cURL-Erweiterung aktivieren.
<?php
require __DIR__ . '/Cryptanio.php';
$key = getenv('CRYPTANIO_API_KEY');
$project = getenv('CRYPTANIO_PROJECT_ID');
if (!$key || !$project) throw new RuntimeException('Set API key and project ID');
$api = new Cryptanio($key);
$page = $api->listEvents(['project' => $project, 'limit' => 25]);
echo json_encode($page, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);Um die Zahlungsdaten einer bestehenden Rechnung zu lesen, tragen Sie ihre ID in CRYPTANIO_RESOURCE_ID ein. Das Beispiel erhält das erforderliche payment_route, das zurückgegebene payment_uri für den QR-Code und das genaue checkout_url. Übergeben Sie das Ergebnis dem Zahler über Ihre Oberfläche, nicht über öffentliche Protokolle. Beträge bleiben Zeichenketten, fehlende Felder werden ausgelassen.
<?php
require __DIR__ . '/Cryptanio.php';
$key = getenv('CRYPTANIO_API_KEY');
$invoiceID = getenv('CRYPTANIO_RESOURCE_ID');
if (!$key || !$invoiceID) throw new RuntimeException('Set API key and invoice ID');
$api = new Cryptanio($key);
$invoice = $api->getInvoice($invoiceID);
$payment = array_intersect_key($invoice, array_fill_keys([
'chain', 'asset', 'address', 'amount', 'expires_at',
'payment_route', 'payment_uri', 'checkout_url'
], true));
echo json_encode($payment, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);Go
Datei in einem cryptanio/-Verzeichnis Ihres Go-Moduls ablegen. Beispiel nutzt Modul example.local/myapp; Importpfad durch eigenen Modulnamen ersetzen. Keine externen Abhängigkeiten nötig.
package main
import (
"context"
"fmt"
"os"
"example.local/myapp/cryptanio"
)
func main() {
key, project := os.Getenv("CRYPTANIO_API_KEY"), os.Getenv("CRYPTANIO_PROJECT_ID")
if key == "" || project == "" { panic("Set API key and project ID") }
api, err := cryptanio.New(key, "", 0)
if err != nil { panic(err) }
page, err := api.ListEvents(context.Background(), map[string]any{
"project": project, "limit": 25,
})
if err != nil { panic(err) }
fmt.Println(page)
}Um die Zahlungsdaten einer bestehenden Rechnung zu lesen, tragen Sie ihre ID in CRYPTANIO_RESOURCE_ID ein. Das Beispiel erhält das erforderliche payment_route, das zurückgegebene payment_uri für den QR-Code und das genaue checkout_url. Übergeben Sie das Ergebnis dem Zahler über Ihre Oberfläche, nicht über öffentliche Protokolle. Beträge bleiben Zeichenketten, fehlende Felder werden ausgelassen.
package main
import (
"context"
"encoding/json"
"os"
"example.local/myapp/cryptanio"
)
func main() {
key, invoiceID := os.Getenv("CRYPTANIO_API_KEY"), os.Getenv("CRYPTANIO_RESOURCE_ID")
if key == "" || invoiceID == "" { panic("Set API key and invoice ID") }
api, err := cryptanio.New(key, "", 0)
if err != nil { panic(err) }
invoice, err := api.GetInvoice(context.Background(), invoiceID)
if err != nil { panic(err) }
payment := make(map[string]any)
for _, field := range []string{
"chain", "asset", "address", "amount", "expires_at",
"payment_route", "payment_uri", "checkout_url",
} {
if value, ok := invoice[field]; ok { payment[field] = value }
}
if err := json.NewEncoder(os.Stdout).Encode(payment); err != nil { panic(err) }
}Rust
Datei als src/cryptanio.rs, Beispiel als src/main.rs speichern. Folgende Abhängigkeiten zu Cargo.toml hinzufügen. Synchroner blockierender Client: nicht direkt in asynchronem Worker ausführen.
[dependencies]
reqwest = { version = "=0.12.24", default-features = false, features = ["blocking", "json", "rustls-tls"] }
serde_json = "=1.0.145"mod cryptanio;
use cryptanio::Cryptanio;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let api = Cryptanio::new(&std::env::var("CRYPTANIO_API_KEY")?)?;
let project = std::env::var("CRYPTANIO_PROJECT_ID")?;
let page = api.list_events(&[("project", &project), ("limit", "25")])?;
println!("{page}");
Ok(())
}Um die Zahlungsdaten einer bestehenden Rechnung zu lesen, tragen Sie ihre ID in CRYPTANIO_RESOURCE_ID ein. Das Beispiel erhält das erforderliche payment_route, das zurückgegebene payment_uri für den QR-Code und das genaue checkout_url. Übergeben Sie das Ergebnis dem Zahler über Ihre Oberfläche, nicht über öffentliche Protokolle. Beträge bleiben Zeichenketten, fehlende Felder werden ausgelassen.
mod cryptanio;
use cryptanio::Cryptanio;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let api = Cryptanio::new(&std::env::var("CRYPTANIO_API_KEY")?)?;
let invoice = api.get_invoice(&std::env::var("CRYPTANIO_RESOURCE_ID")?)?;
let mut payment = serde_json::Map::new();
for field in ["chain", "asset", "address", "amount", "expires_at",
"payment_route", "payment_uri", "checkout_url"] {
if let Some(value) = invoice.get(field) {
payment.insert(field.to_owned(), value.clone());
}
}
println!("{}", serde_json::Value::Object(payment));
Ok(())
}Methoden aufrufen
Node.js und PHP nutzen listEvents, Python und Rust list_events, Go ListEvents. Jede Methode entspricht einer Anfrage in der Referenz. Filter sind Objekt/Map oder in Rust eine Paarliste. Go-Methoden nehmen immer zuerst context.Context. Unbekannte Filter werden vor dem Senden abgelehnt.
| Node.js / PHP-Methode | HTTP |
|---|---|
createWatch | POST /v1/watches |
listWatches | GET /v1/watches |
getWatch | GET /v1/watches/{id} |
deleteWatch | DELETE /v1/watches/{id} |
listEvents | GET /v1/events |
listPayments | GET /v1/payments |
createInvoice | POST /v1/invoices |
listInvoices | GET /v1/invoices |
getInvoice | GET /v1/invoices/{id} |
cancelInvoice | POST /v1/invoices/{id}/cancel |
createEndpoint | POST /v1/endpoints |
listEndpoints | GET /v1/endpoints |
deleteEndpoint | DELETE /v1/endpoints/{id} |
streamEvents | GET /v1/stream |
getHealth | GET /v1/health |
listChains | GET /v1/chains |
Überwachungs- und Webhook-Erstellung benötigen Anfrageinhalt. Einzelressourcen-Methoden nehmen Zeichenfolgen-ID. createInvoice(body, idempotencyKey) erfordert Schlüssel mit 16–80 ASCII-Zeichen: Buchstaben, Ziffern, Bindestriche oder Unterstriche. Bei Wiederholung gleichen Schlüssel und Inhalt nutzen; SDK erzeugt keine neuen Schlüssel und wiederholt nicht automatisch. Inhalte, Fehler und Rechte je Methodenseite prüfen.
Antworten, Fehler und Streaming
JSON-Antworten behalten Feldnamen; IDs, Beträge und Cursor bleiben Zeichenfolgen. Seitennavigation erfolgt manuell laut Methodenbeschreibung. Fehler liefern HTTP-Status, code, message und Retry-After. Ohne HTTP-Antwort ist status 0 (Rust nutzt None). Keine Weiterleitungen. Reguläre JSON-Antworten sind auf 8 MiB begrenzt. Standard-Timeout: 30 Sekunden, einstellbar bis 300. In Python gilt dies pro Netzwerkaktion; sonst für die gesamte Anfrage einschließlich Streaming. Timeout beweist keine nicht ausgeführte Schreibaktion.
| Sprache / Fehler | Felder |
|---|---|
| Node.js / Python: ApiError | status, code, message, retry_after |
| PHP: CryptanioError | status, apiCode, getMessage(), retryAfter |
| Go: *APIError | Status, Code, Message, RetryAfter |
| Rust: ApiError | status: Option<u16>, code, message, retry_after |
streamEvents liefert rohe SSE-Bytes ohne Wiederverbindung oder Ereignisparsing: Node.js ReadableStream, schließbare Python-HTTP-Antwort, Go io.ReadCloser oder Rust blocking::Response. Stream bei Nichtbedarf freigeben. PHP übergibt Blöcke an Callback; false beendet. Streaming ersetzt Webhooks nicht und garantiert kein Replay; siehe SSE-Regeln.
Ihre erste Überwachung
In Account ein Projekt mit aktivem Monitoring und einen Schlüssel mit watches- und events-Berechtigungen erstellen. Erforderliche Kontoverifizierung abschließen. Projekt-ID aus Einstellungen kopieren; nur tatsächlich gewünschte Adresse hinzufügen.
CRYPTANIO_API_KEY und CRYPTANIO_PROJECT_ID in Serverumgebung setzen. Beispieladresse durch eigene ersetzen. Anfrage legt echte Überwachung an; simuliert keine Transaktion.
#!/usr/bin/env bash
set -euo pipefail
: "${CRYPTANIO_API_KEY:?Set CRYPTANIO_API_KEY}"
: "${CRYPTANIO_PROJECT_ID:?Set CRYPTANIO_PROJECT_ID}"
json_string() {
local text="$1" char code index output='"'
for ((index=0; index<${#text}; index++)); do
char="${text:index:1}"
case "$char" in
'"'|'\') output+="\\$char" ;;
*) printf -v code '%d' "'$char"
if ((code < 32)); then printf -v char '\\u%04x' "$code"; fi
output+="$char" ;;
esac
done
printf '%s"' "$output"
}
response_file="$(mktemp)"
trap 'rm -f "$response_file"' EXIT
transfer_status=0
http_status="$(curl \
--silent --show-error --max-time 30 --request POST \
--header "Authorization: Bearer $CRYPTANIO_API_KEY" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data-binary '{"project":'"$(json_string "$CRYPTANIO_PROJECT_ID")"',"chain":"ethereum","address":"0x52908400098527886E0F7030069857D2E4169EE7","asset":"native","label":"Treasury"}' \
"https://api.cryptanio.com/v1/watches" \
--output "$response_file" --write-out '%{http_code}')" || transfer_status=$?
if [[ "$http_status" == 2?? ]]; then
cat "$response_file"
exit "$transfer_status"
fi
printf 'HTTP %s\n' "$http_status" >&2
cat "$response_file" >&2
exit 1
Eine erfolgreiche Antwort enthält id: speichern Sie diesen Wert. GET /v1/watches/{id} liefert die Überwachung und Einstellungen, keine Zahlungen. Erkannte Aktivitäten mit GET /v1/events, gefiltert nach watch_id, abrufen. Eine leere Liste vor der Transaktionserkennung ist normal. Antwort, Fehler und Beispiele in anderen Sprachen.
Payments-Rechnungen
Payments für Ihr Projekt aktivieren und unterstützte Adressen in Account zum Pool hinzufügen. project ausdrücklich senden, statt die Standardprojektauswahl zu nutzen. amount ist eine Zeichenfolge in Kryptoasset-Einheiten; invoice_currency/invoice_amount beschreiben separat den Angebotspreis Ihrer Bestellung.
CRYPTANIO_PROJECT_ID auf Payments-Projekt und CRYPTANIO_API_KEY auf Schlüssel mit invoices-Recht setzen. CRYPTANIO_OPERATION_ID muss für neue Bestellung eindeutig sein; bei derselben Aktion wiederverwenden. Rechnung wird in Live-Daten erstellt.
#!/usr/bin/env bash
set -euo pipefail
: "${CRYPTANIO_API_KEY:?Set CRYPTANIO_API_KEY}"
: "${CRYPTANIO_OPERATION_ID:?Set CRYPTANIO_OPERATION_ID}"
: "${CRYPTANIO_PROJECT_ID:?Set CRYPTANIO_PROJECT_ID}"
json_string() {
local text="$1" char code index output='"'
for ((index=0; index<${#text}; index++)); do
char="${text:index:1}"
case "$char" in
'"'|'\') output+="\\$char" ;;
*) printf -v code '%d' "'$char"
if ((code < 32)); then printf -v char '\\u%04x' "$code"; fi
output+="$char" ;;
esac
done
printf '%s"' "$output"
}
response_file="$(mktemp)"
trap 'rm -f "$response_file"' EXIT
transfer_status=0
http_status="$(curl \
--silent --show-error --max-time 30 --request POST \
--header "Authorization: Bearer $CRYPTANIO_API_KEY" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header "Idempotency-Key: $CRYPTANIO_OPERATION_ID" \
--data-binary '{"project":'"$(json_string "$CRYPTANIO_PROJECT_ID")"',"invoice_currency":"USD","invoice_amount":"12.50","reference":"order-42"}' \
"https://api.cryptanio.com/v1/invoices" \
--output "$response_file" --write-out '%{http_code}')" || transfer_status=$?
if [[ "$http_status" == 2?? ]]; then
cat "$response_file"
exit "$transfer_status"
fi
printf 'HTTP %s\n' "$http_status" >&2
cat "$response_file" >&2
exit 1
Schlüssel muss invoices und Payments erlauben; Monitoring-Beispielschlüssel kann auf anderen Dienst begrenzt sein. Idempotency-Key enthält 16-80 ASCII-Buchstaben, Ziffern, - und _. Dieselbe normalisierte Anfrage mit gleichem Schlüssel liefert vorhandene Rechnung mit 201; geänderter Inhalt liefert 409 conflict. Aktionsschlüssel gelten kontoweit. reference ersetzt sie nicht.
Zeigen Sie dem Käufer das zurückgegebene Netzwerk, den Vermögenswert, die Adresse, amount und die Frist. Wenn payment_route vorhanden ist, übergeben Sie dessen kind und den genauen Zeichenkettenwert value: destination_tag, memo, comment oder reference ist nötig, um die Zahlung dieser Rechnung zuzuordnen. Das Bestellfeld reference ist davon getrennt.
Verwenden Sie das zurückgegebene payment_uri für den Zahlungs-QR-Code, falls vorhanden. Eine Solana-Pay-Referenz ist kein Wallet-Memo: Ersetzen Sie die URI nicht durch eine einfache Adresse und setzen Sie sie nicht neu zusammen. Kann die Wallet das erforderliche Zuordnungsmerkmal nicht übermitteln, bieten Sie dem Zahler checkout_url oder eine kompatible Wallet an.
checkout_url ist die gehostete Zahlungsseite für neue Rechnungen. Geben Sie nur die genau zurückgegebene URL an den Zahler weiter; bilden Sie sie nicht aus der ID. Der Link zeigt Zahlungsdetails und Status und gehört nicht in öffentliche Protokolle. Fehlt er, zeigen Sie die vollständigen Zahlungsdaten. Eine Browserweiterleitung bestätigt keine Zahlung: Prüfen Sie die API oder einen verifizierten Webhook.
asked kann zur Unterscheidung von Bestellungen von amount abweichen. Gleichen Sie mit amount_raw als Ganzzahl beliebiger Genauigkeit ab. Die Standard-TTL beträgt 60 Minuten, maximal 10080 Minuten. Rechnungslisten akzeptieren before, liefern aber kein next_before: Verwenden Sie die ID des letzten Elements und beenden Sie bei einer leeren Seite.
Customer
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
id | string | Ja | Kundenkennung in Ihrem System. maxLength: 120 |
Product
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
id | string | Nein | Produktkennung in Ihrem System. maxLength: 120 |
name | string | Nein | Produktname. maxLength: 200 |
quantity | integer | Nein | Menge. minimum: 1; maximum: 1000000 |
Payer
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
comment | string | Ja | Kommentar des Zahlenden. maxLength: 500 |
InvoiceMetadata
Bis zu 20 Paare, höchstens 8192 JSON-Bytes. Keine Geheimnisse einschließen.
object Bis zu 20 Paare, höchstens 8192 JSON-Bytes. Keine Geheimnisse einschließen.
Monitoring-Überwachungen
Eine Überwachung gehört zu einem Monitoring-Projekt. Dieselbe Adresse lässt sich in mehreren Projekten mit eigenen Richtungs- und Asset-Regeln verwenden. Adressbuchlisten und Address Sources in Account verbinden; diese REST API stellt deren Verwaltungsbefehle nicht bereit.
Liste nach absteigender ID. Falls next_before vorhanden, in nächster Anfrage als before senden, Projekt und Filter beibehalten. limit standardmäßig 50, höchstens 200. IDs als Zeichenfolgen speichern. Entfernte Überwachungen verlassen aktive Liste; Adresse bleibt in anderen Projekten und Adressbuch.
Ereignisse und Verlauf
/v1/events liefert dienstübergreifend für Schlüssel verfügbare Ereignisse; /v1/payments ist auf Payments begrenzt. Filter: project, address, chain, type, watch_id, tx_id. before ist ID-Cursor, kein Datum; kein from/to-Filter. next_before ruft nächste Seite ab.
Erkannte Ereignisse sind bis zu 30 Tage verfügbar. Dies ist kein Archiv aller zugestellten Nachrichten: notice und webhook.test sind darüber nicht garantiert wiederherstellbar. REST Event hat ein eigenes, von Webhooks getrenntes Schema; innerhalb von v1 können Felder hinzukommen.
Event
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
event_id | string | Ja | Undurchsichtige Kennung; als Zeichenfolge behalten. minLength: 1 |
event_type | string | Ja | Ereignistyp; neue Typen können hinzukommen. |
chain | string | Ja | Netzwerkcode. |
service | string | Nein | Dienst, falls bekannt. |
watch_id | string | Nein | Überwachungs-ID des Projekts, falls zugeordnet. minLength: 1 |
occurred_at | string | Ja | UTC-Datum und -Uhrzeit nach RFC 3339.date-time |
payment | object | null | Ja | Zahlungsdokument oder null bei Nichtzahlungsereignis. GET /events liefert keine contract/notice-Inhalte. |
sandbox | boolean | Nein | Testereignis; ohne Angabe false. |
EventPayment
REST/SSE-Zahlungsdokument. Felder hängen von Ereignis und Netzwerk ab; nicht das normalisierte Webhook-v1-Format.
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
tx_id | string | Nein | Transaktionskennung. |
index | integer | Nein | Überweisungsindex innerhalb der Transaktion. minimum: 0 |
height | integer | Nein | Blockhöhe, wenn bekannt. minimum: 0 |
address | string | Nein | Beobachtete Adresse. |
asset | string | Nein | REST/SSE-Asset: Zeichenfolgenkennung, nicht das Webhook-Asset-Objekt. |
amount_raw | string | Nein | Ganzzahliger Betrag in kleinsten Einheiten als Zeichenfolge. pattern: ^[0-9]+$ |
amount | string | Nein | Exakter Dezimalbetrag als Zeichenfolge; keine Gleitkommazahlen verwenden. pattern: ^[0-9]+(?:\.[0-9]+)?$ |
decimals | integer | Nein | Dezimalstellen. minimum: 0 |
confirmations | integer | Nein | Bestätigungen. minimum: 0 |
revision | integer | Nein | Revision des Überweisungsstatus. minimum: 0 |
direction | string | Nein | Richtung relativ zur beobachteten Adresse.in, out |
simulated | boolean | Nein | Simuliertes Ereignis. |
late | boolean | Nein | Verspätet erkannte Überweisung. |
block_hash | string | Nein | Blockhash. |
match_key | string | Nein | Zuordnungskennung, sofern vom Netzwerk verwendet. |
meta | object | Nein | |
invoice | object | Nein | |
customer | object | Nein | |
product | object | Nein | |
payer | object | Nein | |
metadata | object | Nein |
Webhook-Ereignisse
Zustellung erfolgt mindestens einmal: Ereignisse können mehrfach ankommen. Nach Signaturprüfung innerhalb der Integration anhand von event_id deduplizieren. Verarbeitung und Geschäftsänderung in einer Datenbanktransaktion speichern. tx_id/address/asset ersetzt event_id nicht: Dieser Schlüssel fasst verschiedene Übergänge, Richtungen und Projekte zusammen.
event_type und event_id aus dem signierten Inhalt lesen. X-Event-Type/X-Event-Id-Header sind nicht im HMAC enthalten; bei Nutzung mit Inhalt vergleichen. Beim Aktualisieren project_id, direction und payment.revision berücksichtigen. Zustellreihenfolge nicht voraussetzen; unbekannte Typen sicher ignorieren und zur Diagnose behalten.
| Familie | Inhalt |
|---|---|
| payment.pending / confirmed / rolled_back | Eingehende Zahlung |
| debit.pending / confirmed / rolled_back | Ausgehende Zahlung |
| contract.approval / owner_added / owner_removed / threshold_changed / permissions_changed | contract |
| asset.unexpected | contract; Asset wird nicht als akzeptierte Zahlung gutgeschrieben |
| account.notice / account.notification / treasury.alarm / subscription.notice | notice.subject, notice.text |
| webhook.test | Steuerungsereignis ohne Zahlung |
schema_version: v1 enthält je nach Ereignistyp payment, contract oder notice; webhook.test nichts davon. IDs und Beträge sind Zeichenfolgen. amount_raw enthält kleinste Einheiten; amount eine Dezimaldarstellung. Netzwerke und Assets über chains prüfen. Vollständige Objektschemata in OpenAPI.
| Header | Bedeutung |
|---|---|
| X-Timestamp | Unix-Sekunden zum Signaturzeitpunkt |
| X-Signature | hex HMAC-SHA256(timestamp + '.' + raw body) |
| X-Event-Id / X-Event-Type | Mit dem signierten Inhalt vergleichen |
| X-Attempt | Versuchsnummer ab 1 |
Nach dauerhafter Ereignisannahme 2xx zurückgeben. Versuchstimeout: 10 Sekunden. Netzwerkfehler, 408, 425, 429 und 5xx werden bis zu 24 Stunden wiederholt, mit Verzögerungen von 2 Sekunden bis 15 Minuten und Zufallsstreuung; Retry-After beachten. Keine Weiterleitungen. Andere 3xx/4xx beenden Zustellung; 410 deaktiviert Ziel und Rückstau.
{
"schema_version": "v1",
"event_id": "2300",
"event_type": "payment.confirmed",
"occurred_at": "2026-10-06T10:00:00Z",
"project_id": "1002",
"service": "monitoring",
"mode": "test",
"sandbox": true,
"payment": {
"chain": "ethereum",
"direction": "in",
"asset": {
"symbol": "ETH"
},
"address": "0x52908400098527886E0F7030069857D2E4169EE7",
"tx_id": "simulated_2300",
"index": 0,
"amount": "1.000000000000000000",
"amount_raw": "1000000000000000000",
"decimals": 18,
"confirmations": 0,
"revision": 1,
"simulated": true
}
}Webhook
Öffentlicher signierter Webhook-v1-Inhalt. payment.* und debit.* enthalten payment; contract.* und asset.unexpected enthalten contract; webhook.test hat keine Geschäftsdaten; account.notice, account.notification, treasury.alarm und subscription.notice enthalten notice. Zustellwiederholungen über event_id deduplizieren.
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
schema_version | string | Ja | Webhook-Inhaltsversion.v1 |
event_id | string | Ja | Ereignis-ID: unverändert bei Zustellwiederholungen. Verschiedene Zustände können verschiedene event_id haben. minLength: 1 |
event_type | string | Ja | Typ im signierten Inhalt; nach Signaturprüfung verwenden. Neue Typen können hinzukommen. |
occurred_at | string | Ja | UTC-Datum und -Uhrzeit nach RFC 3339.date-time |
project_id | string | Ja | Undurchsichtige Kennung; als Zeichenfolge behalten. minLength: 1 |
service | string | Nein | Projektdienst, falls zutreffend. |
mode | string | Ja | Ereignismodus.live, test |
sandbox | boolean | Ja | Ausdrückliches Simulationskennzeichen. |
payment | object | Nein | |
contract | object | Nein | |
invoice | object | Nein | |
customer | object | Nein | |
product | object | Nein | |
payer | object | Nein | |
metadata | object | Nein | |
notice | object | Nein |
WebhookPayment
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
chain | string | Ja | Netzwerkcode. |
direction | string | Ja | Eingehende Zahlung: in; ausgehende Abbuchung: out.in, out |
asset | object | Ja | |
address | string | Ja | Beobachtete Adresse. |
tx_id | string | Ja | Transaktions-ID. |
index | integer | Ja | Überweisungsindex; 0 nicht für jedes Netzwerk voraussetzen. minimum: 0 |
height | integer | Nein | Blockhöhe, falls bekannt. minimum: 0 |
block_hash | string | Nein | Blockhash, falls bekannt. |
match_key | string | Nein | Netzwerkspezifische Zuordnungskennung, falls zutreffend. |
amount | string | Ja | Exakter Dezimalbetrag als Zeichenfolge; keine Gleitkommazahlen verwenden. pattern: ^[0-9]+(?:\.[0-9]+)?$ |
amount_raw | string | Ja | Ganzzahliger Betrag in kleinsten Einheiten als Zeichenfolge. pattern: ^[0-9]+$ |
decimals | integer | Ja | Dezimalstellen. minimum: 0 |
confirmations | integer | Ja | Bestätigungen. minimum: 0 |
revision | integer | Ja | Revision des Überweisungsstatus. Verschiedene event_id nicht anhand der Transaktionsidentität zusammenfassen. minimum: 0 |
late | boolean | Nein | Verspätet erkannte Überweisung; nicht gleich dem Rechnungsstatus late. |
simulated | boolean | Nein | Simulierte Überweisung. |
valuation | object | Nein |
WebhookAsset
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
symbol | string | Nein | Symbol, falls bekannt; reicht nicht zur Tokenidentifizierung. |
standard | string | Nein | Tokenstandard, falls bekannt. |
contract | string | Nein | Tokenvertrag in seinem Netzwerk, falls zutreffend. |
identifier | string | Nein | Andere netzwerkspezifische Tokenkennung. |
WebhookContract
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
chain | string | Ja | Netzwerkcode. |
address | string | Ja | Beobachtete Adresse oder Vertrag. |
tx_id | string | Ja | Transaktions-ID. |
index | integer | Ja | Ereignisindex. minimum: 0 |
height | integer | Nein | Blockhöhe. minimum: 0 |
block_hash | string | Nein | Blockhash. |
kind | string | Nein | Art der Änderung. |
asset | string | Nein | Kennung des betroffenen Assets, falls bekannt. |
detail | object | Nein | |
simulated | boolean | Nein | Simuliertes Ereignis. |
WebhookInvoice
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
id | string | Ja | Undurchsichtige Kennung; als Zeichenfolge behalten. minLength: 1 |
reference | string | Nein | Bestellreferenz. |
status | string | Nein | pending wartet auf Zahlung; seen erkannt; partial teilweise bezahlt; paid beglichen; underpaid/overpaid/late erfordern Entscheidung; expired Frist abgelaufen; canceled storniert.pending, seen, paid, underpaid, partial, overpaid, expired, late, canceled |
currency | string | Nein | Währung des Bestellangebots. |
amount | string | Nein | Exakter Dezimalbetrag als Zeichenfolge; keine Gleitkommazahlen verwenden. pattern: ^[0-9]+(?:\.[0-9]+)?$ |
Notice
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
subject | string | Ja | Betreff der Mitteilung. |
text | string | Ja | Mitteilungstext. |
Valuation
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
currency | string | Ja | Bewertungswährung, etwa USD. |
amount | string | Ja | Exakter Dezimalbetrag als Zeichenfolge; keine Gleitkommazahlen verwenden. pattern: ^[0-9]+(?:\.[0-9]+)?$ |
rate | string | Ja | Asset-Wechselkurs als Dezimalzeichenfolge. pattern: ^[0-9]+(?:\.[0-9]+)?$ |
rate_at | string | Ja | UTC-Datum und -Uhrzeit nach RFC 3339.date-time |
provider | string | Nein | Name der Kursquelle, falls bekannt. |
Signaturen prüfen
HMAC vor JSON-Parsing über ursprüngliche Inhaltsbytes einschließlich Leerzeichen und Zeilenumbrüchen prüfen. Frischeprüfung begrenzt Replay, ersetzt aber keine dauerhafte event_id-Deduplizierung. Beispiele akzeptieren nur Hexsignaturen mit 64 Zeichen und Zeitstempel innerhalb von 300 Sekunden der Serverzeit. Geheimnis des konkreten Webhook-Ziels nutzen.
import { createHmac, timingSafeEqual } from "node:crypto";
import { TextDecoder } from "node:util";
// rawBody is the original HTTP request Buffer, before JSON.parse or serialization.
export function verifyWebhook(secret, timestamp, rawBody, signature, nowSeconds = Math.floor(Date.now() / 1000)) {
if (typeof secret !== "string" || secret.length === 0 || !Buffer.isBuffer(rawBody) || rawBody.length === 0 ||
typeof timestamp !== "string" || !/^(0|[1-9][0-9]*)$/.test(timestamp) ||
typeof signature !== "string" || !/^[0-9a-f]{64}$/i.test(signature) ||
!Number.isSafeInteger(nowSeconds) || nowSeconds < 0) return false;
const signedAt = Number(timestamp);
if (!Number.isSafeInteger(signedAt) || Math.abs(nowSeconds - signedAt) > 300) return false;
const expected = createHmac("sha256", secret).update(timestamp).update(".").update(rawBody).digest();
return timingSafeEqual(expected, Buffer.from(signature, "hex"));
}
// headers is Node.js request.headers (lowercase names). Optional X-Event-Id/Type
// headers are not signed separately; compare them with the verified body.
export function readSignedWebhook(secret, timestamp, rawBody, signature, headers = {}, nowSeconds) {
if (!verifyWebhook(secret, timestamp, rawBody, signature, nowSeconds) ||
headers === null || typeof headers !== "object" || Array.isArray(headers)) return null;
let event;
try {
event = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(rawBody));
} catch {
return null;
}
if (event === null || typeof event !== "object" || Array.isArray(event) || event.schema_version !== "v1" ||
typeof event.event_id !== "string" || event.event_id.length === 0 ||
typeof event.event_type !== "string" || event.event_type.length === 0) return null;
for (const [header, field] of [["x-event-id", "event_id"], ["x-event-type", "event_type"]]) {
if (headers[header] !== undefined && headers[header] !== event[field]) return null;
}
return event;
}
Node.js-Beispiel herunterladen
package webhook
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"strconv"
"time"
"unicode/utf8"
)
// VerifyWebhook checks the original HTTP body bytes before parsing JSON.
// Optional nowSeconds is used only for deterministic tests.
func VerifyWebhook(secret, timestamp string, rawBody []byte, signature string, nowSeconds ...int64) bool {
if secret == "" || len(rawBody) == 0 || len(signature) != 64 || len(nowSeconds) > 1 {
return false
}
signedAt, err := strconv.ParseInt(timestamp, 10, 64)
if err != nil || signedAt < 0 || strconv.FormatInt(signedAt, 10) != timestamp {
return false
}
now := time.Now().Unix()
if len(nowSeconds) == 1 {
now = nowSeconds[0]
}
if now < 0 || now-signedAt < -300 || now-signedAt > 300 {
return false
}
provided, err := hex.DecodeString(signature)
if err != nil || len(provided) != sha256.Size {
return false
}
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(timestamp))
mac.Write([]byte("."))
mac.Write(rawBody)
return hmac.Equal(mac.Sum(nil), provided)
}
// WebhookEvent contains only routing fields. Parse other fields from rawBody
// after ReadSignedWebhook succeeds; unknown fields are allowed.
type WebhookEvent struct {
SchemaVersion string `json:"schema_version"`
EventID string `json:"event_id"`
EventType string `json:"event_type"`
}
// ReadSignedWebhook extracts event_id/type only from the verified body.
// X-Event-Id/Type are not signed separately; nonempty values must match the body.
func ReadSignedWebhook(secret, timestamp string, rawBody []byte, signature, eventIDHeader, eventTypeHeader string,
nowSeconds ...int64) (*WebhookEvent, error) {
if !VerifyWebhook(secret, timestamp, rawBody, signature, nowSeconds...) {
return nil, errors.New("invalid webhook signature or timestamp")
}
var event WebhookEvent
if !utf8.Valid(rawBody) || json.Unmarshal(rawBody, &event) != nil || event.SchemaVersion != "v1" ||
event.EventID == "" || event.EventType == "" {
return nil, errors.New("invalid webhook body")
}
if eventIDHeader != "" && eventIDHeader != event.EventID || eventTypeHeader != "" && eventTypeHeader != event.EventType {
return nil, errors.New("webhook headers do not match the signed body")
}
return &event, nil
}
Webhook-Endpunkte
Eine öffentliche HTTPS-URL auf Port 443 für ein bestimmtes Projekt hinzufügen. Zugangsdaten, Fragmente, Weiterleitungen und nicht öffentliche Ziele sind unzulässig. Bis zu 20 Endpunkte pro Konto. Jeder hat ein eigenes Geheimnis, das nur bei der ersten Erstellung ausgegeben wird; auf Ihrem Server speichern.
Dieselbe URL für dasselbe Projekt und denselben Modus erneut erstellen liefert 200 und den vorhandenen Endpunkt ohne Geheimnis. Ein neuer Endpunkt liefert 201. DELETE liefert 200 mit id und deleted: true, auch bei sicherer Wiederholung. Ein Schlüssel sieht nur seinen Modus und erlaubte Projekte; Zustellung folgt den Projekteinstellungen.
SSE-Stream
SSE dient serverseitiger Integration und Live-Anzeige; keine Garantie für Zustellung oder Nachholung. Serverseitigen HTTP-Client mit Bearer-Header nutzen. Browser-EventSource kann diesen nicht senden; API-Schlüssel nicht in Browsercode oder Querystring setzen.
Nachrichten nutzen event: payment und eigenes StreamEvent-Format, nicht webhook v1 oder REST Event. Kommentare beginnen mit Doppelpunkt; Heartbeats etwa alle 20 Sekunden. retry: 5000 ist ein Wiederverbindungshinweis. Nach Trennung verfügbare Blockchain-Ereignishistorie über events abrufen.
StreamEvent
JSON in SSE data; unterscheidet sich von webhook v1. Nichtzahlungsereignisse lassen payment weg und können contract enthalten.
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
event_id | string | Ja | Undurchsichtige Kennung; als Zeichenfolge behalten. minLength: 1 |
event_type | string | Ja | Ereignistyp; neue Typen können hinzukommen. |
chain | string | Ja | Netzwerkcode. |
service | string | Nein | Dienst, falls bekannt. |
watch_id | string | Nein | Überwachungs-ID des Projekts, falls zugeordnet. minLength: 1 |
occurred_at | string | Ja | UTC-Datum und -Uhrzeit nach RFC 3339.date-time |
payment | object | null | Nein | Zahlungsdokument oder null bei Nichtzahlungsereignis. GET /events liefert keine contract/notice-Inhalte. |
sandbox | boolean | Nein | Testereignis; ohne Angabe false. |
project_id | string | Nein | Undurchsichtige Kennung; als Zeichenfolge behalten. minLength: 1 |
project_name | string | Nein | Projektname. |
url | string | Nein | Link zum Ereignis in Account.uri |
contract | object | Nein | |
mode | string | Nein | live oder test.live, test |
Zahlungs- und Rechnungszustände
Blockchain-Zahlungsstatus und Bestellstatus unterscheiden sich. payment.pending bezeichnet Erkennung vor ausreichender Bestätigung; payment.confirmed bedeutet, dass die Bestätigungsregel des Netzwerks/Projekts erfüllt ist; payment.rolled_back meldet eine Rücknahme. Bestellungen nicht bei pending, ausgehenden Abbuchungen oder simulierten Ereignissen erfüllen.
| Rechnung | Bedeutung |
|---|---|
| pending | Zahlung ausstehend |
| partial | Teil erhalten; Teilzahlungsrichtlinie des Projekts gilt |
| paid | Zahlung akzeptiert |
| underpaid | Unterzahlung erfordert Entscheidung |
| overpaid | Überzahlung erfordert Entscheidung nach geltender Richtlinie |
| late | Zahlung nach Fristablauf erfordert Entscheidung |
| expired | Zahlungsfrist abgelaufen |
| canceled | Rechnung storniert; Datensatz bleibt lesbar |
needs_decision ist bei underpaid, overpaid und late vorhanden. In Account lösen. Reorg und erneute Aufnahme können neue Übergänge und neue payment.revision erzeugen; confirmed ist keine bedingungslose Garantie gegen künftige Änderungen.
Fehler und sichere Wiederholungen
{"error":{"code":"forbidden","message":"this API key is read-only"}}HTTP-Status und error.code für Logik nutzen, message für Diagnose. Erfolgreiche Listen enthalten data; einzelne Objekte werden direkt geliefert. Health nutzt eigenes status/version-Schema, auch bei 503. Nicht auf exakten Nachrichtentext verlassen.
| HTTP | Aktion |
|---|---|
| 400 | JSON, Formate und Parameter korrigieren; nicht unverändert wiederholen |
| 401 | Schlüssel, Ablauf, Pause und Widerruf prüfen |
| 403 | Scopes, Lesen/Schreiben, Projekt, Dienst, IP und Kontoverifizierung prüfen |
| 404 | ID, Schlüsselmodus und Zugriff prüfen; Einschränkungen können die Ressource verbergen |
| 402 | Limit für Monitoring-Überwachungen; Tarif prüfen |
| 409 | Konflikt, inaktiver Dienst, belegter Pool oder Limit; code prüfen |
| 429 | Retry-After beachten; gemeinsame Anfragerate des Kontos reduzieren |
| 500 / 503 | Mit begrenztem Backoff wiederholen; Rechnungserstellung nur mit ursprünglichem Idempotency-Key |
Ein Timeout bedeutet nicht, dass die Aktion nicht ausgeführt wurde. Den Aktionsschlüssel einer Rechnung beim Wiederholen nicht ändern. Bei Methoden ohne Duplikatschutz zuerst den Zustand lesen; nicht jeder POST ist idempotent.
Netzwerke und Limits
chains auf gewähltem API-Host für Netzwerk-, Asset-, Funktions- und Bestätigungskatalog nutzen. Eintrag im allgemeinen Katalog garantiert weder Aktivierung in dieser Umgebung noch alle Aktionen. Dienstquoten und Budget in Account prüfen; Preise stehen unter Preise.
Authentifizierte REST-Quote pro Konto: 10 Anfragen/s ohne kostenpflichtigen Dienst, 50 mit kostenpflichtigem Dienst; kurzfristiger Burst: 20/100. Alle Kontoschlüssel und Modi teilen die Quote. Überschreitung liefert 429 mit Retry-After. Dienstquoten und API-Ratenlimits gelten separat.
API-Versionen
Referenz beschreibt v1 in Release 1.0.0 62; aktualisiert 2026-10-10. Vor neuen Funktionen installiertes Release über GET /v1/health prüfen. Dokumentationsversion bestätigt kein Deployment.
| Öffentliche API | Vertrag |
|---|---|
https://api.cryptanio.com | /v1 |
/v1 für stabile Integrationen nutzen. Unversionierter Pfad wählt aktuellen stabilen Vertrag der Umgebung; unbekanntes /vN liefert 404. X-API-Version bezeichnet den Vertrag; X-Server-Version und health.version das Produktrelease, keinen anderen API-Vertrag.
API-Änderungen
Release 1.0.0 62 enthält SDK-Downloads für Node.js, Python, PHP, Go und Rust sowie lokalen MCP für KI-Agenten. Referenz, Markdown und rohe HTTP-Beispiele bleiben separat verfügbar. Keine öffentliche Sandbox. API-Verhalten unverändert.
In v1 sollen Clients zusätzliche Antwortfelder tolerieren. Unbekannten Ereignistyp akzeptieren bedeutet keine Bestellerfüllung oder Zahlungsgutschrift. Änderungen vor Nutzung mit Version der gewählten Umgebung abgleichen.