Documentazione

Costruisci conCryptocardium.

Emetti carte, finanzia account, avvia transazioni e monitora il ciclo di vita — da cURL, da qualsiasi SDK, dal tuo agente AI. L'intera piattaforma è una stabile API REST e un server MCP nativo.

Benvenuto

Cryptocardium è un programma carte no-KYC finanziato con crypto. Ogni azione disponibile nel pannello — apertura account, ricarica, emissione carta, caricamento, spesa, monitoraggio transazioni — è accessibile tramite la stessa API REST e lo stesso server MCP.

Questa documentazione copre tutto: convenzioni (come comunica l'API), risorse (cosa puoi richiedere), eventi (come restare sincronizzati) e integrazioni (Claude, ChatGPT, Cursor, qualsiasi agente).

Le chiavi API vengono generate nel pannello.

Registrati su /account, apri Impostazioni API, clicca "Nuova chiave". Il testo in chiaro completo viene mostrato una sola volta — copialo in un gestore di segreti.

Quickstart

Da zero a una carta virtuale attiva in tre chiamate. L'esempio seguente usa cURL; sostituisci con qualsiasi client HTTP.

1. Autenticazione

Inserisci la tua chiave API nell'intestazione Authorization. Ogni endpoint la richiede.

export CCM_KEY="ccm_live_a1b2c3d4..."

2. Ricarica il treasury

Crea un indirizzo di deposito USDT. Invia i fondi; accreditiamo a conferma.

curl https://api.cryptocardium.com/v1/topups \
  -H "Authorization: Bearer $CCM_KEY" \
  -H "Idempotency-Key: top_$(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "amount_usd": 500, "asset": "USDT", "chain": "tron" }'

3. Emetti una carta & spendi

Scegli un BIN (Visa Platinum per i wallet, Visa Business per le inserzioni), caricalo e sei operativo.

curl https://api.cryptocardium.com/v1/cards \
  -H "Authorization: Bearer $CCM_KEY" \
  -d '{
    "type": "virtual",
    "bin": "489517",
    "load_usd": 300,
    "wallet_provision": ["apple_pay", "google_pay"]
  }'

# → 201 Created · card is live, balance loaded, wallet-ready
Tutto qui.

Quarantasette secondi in mediana, dalla registrazione alla prima autenticazione. Le sezioni successive coprono tutto il resto — gestione degli errori, idempotenza, webhook, configurazione agente — di cui avrai bisogno in produzione.

Autenticazione

Tre tipi di credenziali, scelti in base alla forma di integrazione:

TipoFormatoUtilizzato per
Bearer di sessionesess_…Script interattivi, test, il pannello stesso.
Chiave APIccm_live_…Server di produzione, CI, job pianificati, a lungo termine.
OAuth 2.1 + DCReyJh… (JWT)Agenti che si registrano autonomamente a runtime, grant con scope limitato.

Intestazione Bearer

Tutti e tre transitano attraverso la stessa intestazione:

Authorization: Bearer ccm_live_a1b2c3d4...

Genera una chiave API

Le chiavi vengono generate esclusivamente nel pannello. Non accettiamo mai una richiesta di creazione chiave tramite API senza una sessione autenticata collegata alla sessione del pannello.

  1. Accedi al tuo account.
  2. Apri Impostazioni API.
  3. Clicca Nuova chiave, assegnale un nome riconoscibile, salva il testo in chiaro (mostrato una sola volta).
  4. Archivia in un gestore di segreti. Aggiungi al tuo ambiente come CCM_KEY.
Tratta le chiavi come password.

Una chiave ccm_live_ compromessa porta con sé i permessi a livello di account. Effettua la rotazione tramite /api-settings se sospetti un'esposizione — la revoca è istantanea.

Test & sandbox

Attualmente, le ricariche inferiori a $200 vengono accettate come live ma instradate verso un processore carte sandbox, così puoi integrare senza consumare settlement reali. Gli account di produzione dispongono di toggle sandbox per chiave.

  • Ricarica $200+ → rail di produzione, settlement reale.
  • Ricarica <$200 → rail sandbox, autorizzazioni simulate.
  • Le carte emesse da ricariche sandbox portano "mode": "sandbox".

URL base & versionamento

URL base di produzione:

https://api.cryptocardium.com/v1

Il prefisso v1 fa parte del percorso. v1 è LTS a vita — non verranno mai introdotte modifiche che causano interruzioni sotto di esso. Le modifiche additive (nuovi campi opzionali, nuovi endpoint) vengono rilasciate in modo trasparente.

Le modifiche che causano interruzioni vengono introdotte sotto un nuovo prefisso (v2) con almeno sei mesi di sovrapposizione. Le deprecazioni vengono annunciate tramite webhook (system.deprecation) e il changelog.

Richieste

Tutte le richieste sono esclusivamente HTTPS (TLS 1.3). I corpo delle richieste sono JSON; gli oggetti annidati sono di prima classe. I corpo form-encoded non sono supportati.

  • Content-Type: application/json per gli endpoint di scrittura.
  • <strong>Charset</strong>: sempre UTF-8.
  • Metodi HTTP: GET (lettura), POST (creazione / azione), PATCH (aggiornamento parziale), DELETE (eliminazione).
  • Limiti intestazioni: 8 KB totale, 4 KB per valore.
  • Limite corpo: 25 MB (100 MB per upload di prove per controversie).
  • Timeout: 30 s connessione, 60 s lettura. Le operazioni a lunga esecuzione sono asincrone.

Risposte

Ogni risposta è in JSON. Le risposte di successo restituiscono 200/201/204 con il corpo della risorsa. Gli errori restituiscono un oggetto errore strutturato — vedi Errori.

Envelope standard

{
  "id": "card_8f3a91b7c4d2",
  "object": "card",
  "created_at": "2026-05-19T07:30:00Z",
  "updated_at": "2026-05-19T07:30:00Z",
  ...
}

Timestamp

Tutti i timestamp sono in formato ISO 8601 in UTC, formattati come YYYY-MM-DDTHH:MM:SSZ. L'API non utilizza altri fusi orari.

Valori monetari

Tutti gli importi sono decimali equivalenti in USD nei campi amount_usd. Precisione a due decimali. Internamente supportati da USDT.

Paginazione

Gli endpoint di lista (/topups, /cards, /transactions, …) utilizzano la paginazione basata su cursore. Nessun offset, nessun LIMIT SQL.

GET /v1/transactions?limit=50&cursor=tx_8f3a91b7c4d2
  • limit — dimensione della pagina, predefinito 25, massimo 100.
  • cursor — reinvia il next_cursor dalla risposta precedente.
  • La paginazione segue l'ordinamento naturale di ciascuna risorsa (tipicamente <code>created_at</code> decrescente).
{
  "object": "list",
  "data": [ /* 50 items */ ],
  "has_more": true,
  "next_cursor": "tx_2bea88..."
}

Filtri & ordinamento

Ogni endpoint di lista supporta il filtraggio sui campi principali tramite parametri di query:

GET /v1/transactions
  ?card_id=card_8f3a91b7c4d2
  &status=captured
  &created_after=2026-05-01T00:00:00Z
  &sort=-amount_usd

Il parametro sort accetta un singolo campo; usa il prefisso - per l'ordine decrescente. Consulta il riferimento endpoint di ciascuna risorsa per le chiavi di filtraggio supportate.

Idempotenza

Ogni richiesta di scrittura (POST, PATCH, DELETE) accetta un'intestazione Idempotency-Key. Passa un valore univoco per ogni operazione logica. I tentativi con la stessa chiave restituiscono la risposta originale.

POST /v1/cards
Idempotency-Key: card_create_b9f1a4...
Authorization: Bearer ccm_live_...
  • Le chiavi vengono conservate per 24 ore. Successivamente, la stessa chiave può essere riutilizzata per una nuova operazione.
  • Formato consigliato: <operazione>_<uuid-v4>.
  • Stessa chiave + corpo diverso → 409 Conflict con conflict_idempotency_key.
  • Le richieste GET sono sempre idempotenti e non richiedono (né accettano) l'intestazione.

Limiti di velocità

Per chiave API:

FinestraLimiteNote
Burst 1 s60 reqPicchi brevi tollerati.
1 min1 000 reqSoglia sostenuta.
1 giorno50 000 reqAggregato per chiave.

Ogni risposta include:

X-RateLimit-Limit:     1000
X-RateLimit-Remaining: 943
X-RateLimit-Reset:     1718999999

Quando superi il limite, riceverai 429 Too Many Requests con un'intestazione Retry-After in secondi. Rispettala; applichiamo backoff esponenziale ai comportamenti scorretti.

Errori

Ogni risposta di errore utilizza la stessa struttura:

{
  "object": "error",
  "type": "invalid_request_error",
  "code": "missing_required_field",
  "message": "Field 'bin' is required.",
  "param": "bin",
  "request_id": "req_a9f4b1..."
}

Mappatura stati HTTP

StatoTipoSignificato
400invalid_request_errorPayload malformato, campi mancanti.
401authentication_errorBearer mancante o non valido.
403permission_errorIl Bearer è valido, ma l'azione non è consentita (es. blocco saldo).
404not_found_errorLa risorsa non esiste (o non ti appartiene).
409conflict_errorConflitto di stato (es. chiave idempotenza riutilizzata).
419session_expiredSessione pannello scaduta. Riautenticati.
422validation_errorJSON del payload valido, regola di business non rispettata.
429rate_limit_errorRallenta. Retry-After in secondi.
500api_errorColpa nostra. Abbiamo già ricevuto un avviso.
503service_unavailableEmittente upstream non disponibile. Si consiglia il retry automatico.

Registra sempre il request_id. I ticket di supporto lo referenziano direttamente.

Account

L'account è la tua risorsa radice. Tutto il resto (ricariche, carte, transazioni) appartiene a un account.

Creazione

POST /v1/accounts
{
  "email": "[email protected]",
  "password": "long-random-string"
}

Restituisce immediatamente un bearer di sessione. Nessun KYC, nessun caricamento documenti, nessuna verifica email richiesta per iniziare a usare l'API.

Recupera account corrente

GET /v1/accounts/me
{
  "id": "acc_8f3a91b7c4d2",
  "email": "[email protected]",
  "balance_usd": 487.20,
  "twofa_enabled": true,
  "created_at": "2026-05-18T20:14:00Z"
}

Saldo & treasury

Il saldo dell'account è il pool USDT disponibile per la spesa. Le ricariche lo accreditano, i caricamenti carta e i prelievi lo addebitano.

GET /v1/balance
{
  "object": "balance",
  "available_usd": 487.20,
  "pending_usd": 200.00,
  "updated_at": "2026-05-19T07:30:00Z"
}

pending_usd comprende le ricariche in corso (non ancora confermate) e i caricamenti carta in corso.

Ricariche

Una ricarica è il passaggio asimmetrico in cui depositi crypto on-chain e noi accreditiamo USDT dopo la finalizzazione.

Creazione

POST /v1/topups
{
  "amount_usd": 500,
  "asset": "USDT",
  "chain": "tron"
}

Restituisce un indirizzo di deposito, un URI dati QR e una scadenza (predefinito 60 min). Invia l'importo esatto all'indirizzo; accreditiamo a conferma.

{
  "id": "top_4e21a99c7b",
  "status": "pending",
  "amount_usd": 500,
  "deposit_address": "T9zFR...kQp",
  "qr_data_uri": "data:image/png;base64,...",
  "expires_at": "2026-05-19T08:30:00Z"
}

Ciclo di vita degli stati

StatoSignificato
pendingIn attesa di deposito on-chain.
completedFondi accreditati sul saldo.
expiredFinestra indirizzo chiusa. I depositi tardivi vengono comunque accreditati automaticamente.
cancelledHai chiamato POST /v1/topups/:id/cancel.
errorSettlement fallito (raro). Rimborso automatico.

Preferisci il webhook topup.confirmed al polling — si attiva una sola volta e ti risparmia 30+ poll.

Carte

Le carte sono di due tipi — virtuali (attive in pochi secondi) e fisiche (spedite in 5–9 giorni, vincolate al BIN Visa Gold).

Emissione

POST /v1/cards
{
  "type": "virtual",
  "bin": "489517",
  "load_usd": 300,
  "wallet_provision": ["apple_pay", "google_pay"]
}

Catalogo BIN

BINNomeIdeale perTipo
416842Visa BusinessSpesa pubblicitaria (3-D Secure)Virtuale
557213Mastercard WorldMulti-valuta, premiumVirtuale
489517Visa PlatinumApple & Google PayVirtuale
472305Visa CorporateAbbonamenti SaaSVirtuale
448585Visa GoldSolo fisica (3-D Secure)Fisica

Visualizza PAN + CVV completi

Il numero carta completo, CVV e scadenza vengono restituiti solo tramite una chiamata dedicata e verificata:

GET /v1/cards/:id/pan
{
  "pan": "4895 1712 ●●●● 4218",
  "cvv": "347",
  "expires_at": "2029-08",
  "audit_id": "audit_8c2e3f..."
}

Ogni visualizzazione viene registrata nel trail di audit. Gli agenti devono visualizzare una volta per acquisto, non archiviare mai i dati e cancellarli dalla memoria dopo l'uso.

Operazioni

  • POST /v1/cards/:id/freeze — blocca le autorizzazioni.
  • POST /v1/cards/:id/unfreeze — riprendi.
  • POST /v1/cards/:id/load — aggiungi USDT alla carta.
  • POST /v1/cards/:id/unload — sposta il saldo non speso al treasury.
  • POST /v1/cards/:id/cancel — disattivazione permanente.
  • PATCH /v1/cards/:id/limits — massimali per transazione / mensili per carta.
  • PATCH /v1/cards/:id/mcc — liste di autorizzazione/blocco MCC.
  • PATCH /v1/cards/:id/geo — liste di paesi consentiti.

Caricamenti carta & saldi

Il saldo carta è denominato in USDT equivalente in USD. Un caricamento deduce dal treasury, applica la commissione rail del 2% e accredita la carta.

POST /v1/cards/:id/load
{ "amount_usd": 200 }
{
  "card_id": "card_8f3a91b7c4d2",
  "loaded_usd": 200.00,
  "rail_fee_usd": 4.00,
  "new_card_balance_usd": 200.00,
  "new_treasury_balance_usd": 283.20
}

I caricamenti sono atomici — la chiamata restituisce risposta solo dopo che i fondi si sono spostati.

Transazioni

Ogni autorizzazione, addebito, rimborso e rifiuto è un oggetto transazione. Sono in sola aggiunta e immutabili.

GET /v1/cards/:id/transactions?status=captured&limit=50
{
  "object": "list",
  "data": [
    {
      "id": "tx_b1c2d3",
      "object": "transaction",
      "card_id": "card_8f3a91b7c4d2",
      "status": "captured",
      "amount_usd": 42.95,
      "merchant": { "name": "OpenAI", "mcc": "7372" },
      "auth_response_code": "00",
      "created_at": "2026-05-19T03:14:00Z"
    }
  ],
  "has_more": false
}

Filtra per status, card_id, mcc, merchant_name, created_after, created_before, amount_min, amount_max.

Prelievi

Invia USDT dal treasury a qualsiasi wallet esterno che controlli.

POST /v1/withdrawals
{
  "amount_usd": 100,
  "chain": "tron",
  "address": "T9zFR...kQp"
}

Minimo $10, massimo l'intero saldo. Chain supportate: tron (la più economica), ethereum, bsc. Gli invii cross-network sono irrecuperabili — verifica sempre l'indirizzo.

Dispute

Avvia un chargeback su qualsiasi transazione:

POST /v1/disputes
{
  "transaction_id": "tx_b1c2d3",
  "reason": "duplicate",
  "description": "Merchant charged twice on 2026-05-19, same order #4921."
}

Codici motivo: duplicate, not_received, fraud, not_as_described, cancelled_subscription, other.

Allega prove (ricevute, screenshot, corrispondenza) tramite POST /v1/disputes/:id/evidence. Presentiamo la pratica all'emittente per tuo conto — nessuna commissione aggiuntiva.

Webhooks · iscrizione

I webhook inviano gli eventi al tuo endpoint HTTPS non appena si verificano. Evita il polling; usa i webhook.

POST /v1/webhooks
{
  "url": "https://yourapp.example.com/webhooks/cryptocardium",
  "events": [
    "topup.confirmed",
    "card.issued",
    "transaction.captured",
    "transaction.declined"
  ],
  "description": "Production sync"
}

La risposta contiene un signing_secret — conservalo; ti servirà per verificare i payload. Iscriviti a "*" per ricevere ogni evento.

Webhooks · verifica della firma

Ogni webhook include una firma HMAC-SHA256 nell'intestazione Cryptocardium-Signature:

Cryptocardium-Signature: t=1718999999,v1=4a8b2f0e6c9d...
Cryptocardium-Event-Id:  evt_a1b2c3d4
Cryptocardium-Delivery:  dlv_8f3a91...

Calcola la firma attesa su "{t}.{rawBody}" con il tuo signing_secret. Confronta usando una funzione a tempo costante.

Node.js

import crypto from 'crypto';

export function verify(rawBody, sigHeader, secret) {
  const [t, v1] = sigHeader.split(',')
    .map(s => s.split('=')[1]);
  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${t}.${rawBody}`)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(v1), Buffer.from(expected)
  );
}

Python

import hmac, hashlib

def verify(raw_body: bytes, sig_header: str, secret: str) -> bool:
    parts = dict(p.split('=') for p in sig_header.split(','))
    t, v1 = parts['t'], parts['v1']
    expected = hmac.new(
        secret.encode(),
        f"{t}.{raw_body.decode()}".encode(),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(v1, expected)

PHP

function verify($rawBody, $sigHeader, $secret): bool {
    $parts = [];
    foreach (explode(',', $sigHeader) as $p) {
        [$k, $v] = explode('=', $p, 2);
        $parts[$k] = $v;
    }
    $expected = hash_hmac('sha256',
        "{$parts['t']}.{$rawBody}", $secret);
    return hash_equals($expected, $parts['v1']);
}

Webhooks · tentativi & replay

Consegna at-least-once. Effettuiamo nuovi tentativi per qualsiasi risposta non-2xx o timeout (10 s).

TentativoRitardo
1immediato
230 s
35 min
430 min
52 h
612 h
724 h (finale)

Ripeti qualsiasi evento dal pannello o tramite POST /v1/webhooks/:id/replay/:event_id. Usa l'intestazione Cryptocardium-Event-Id per la deduplicazione lato tuo.

Catalogo eventi

Account account.created account.signed_in account.signed_out account.password_changed account.totp_enabled account.totp_disabled
Top-ups topup.created topup.confirmed topup.expired topup.cancelled topup.error
Cards card.issued card.loaded card.unloaded card.frozen card.unfrozen card.cancelled card.replaced
Tx transaction.authorized transaction.captured transaction.refunded transaction.declined transaction.reversed
Dispute dispute.opened dispute.responded dispute.won dispute.lost
Withdraw withdrawal.created withdrawal.broadcasted withdrawal.confirmed withdrawal.failed
System system.maintenance system.deprecation

Server MCP

Ospitiamo un server Model Context Protocol su https://mcp.cryptocardium.com/v1. Espone oltre 40 strumenti mappati 1:1 sugli endpoint REST, con nomi ottimizzati per gli agenti (create_topup, issue_card, reveal_pan, ecc.).

Trasporto: Streamable HTTP. Autenticazione: OAuth 2.1 con Dynamic Client Registration — gli agenti si registrano autonomamente al primo collegamento, senza necessità di incollare una chiave API nella configurazione dell'agente.

MCP · configurazione client

Claude Desktop / Claude Code

// ~/.config/claude/claude_desktop_config.json
{
  "mcpServers": {
    "cryptocardium": {
      "url": "https://mcp.cryptocardium.com/v1",
      "transport": "http"
    }
  }
}

Cursor / Continue / mcp-cli

# Adds the server, kicks off OAuth DCR on first connect
mcp-cli add cryptocardium \
  --url https://mcp.cryptocardium.com/v1 \
  --auth oauth

Dopo l'autorizzazione nel browser, l'agente ha accesso a ogni strumento del catalogo (o solo a quelli che hai concesso, se hai ristretto lo scope).

MCP · catalogo strumenti

Gli strumenti rispecchiano gli endpoint REST. Un breve esempio (la lista completa è su /api):

Account create_account sign_in get_account enable_2fa
Treasury get_balance create_topup withdraw
Carte issue_card load_card reveal_pan freeze_card set_card_limits
Tx & log list_transactions get_activity file_dispute

MCP · OAuth 2.1 + DCR

Gli agenti si registrano dinamicamente tramite RFC 7591. Flusso:

  1. L'agente esegue POST /oauth/register — riceve client_id & client_secret.
  2. L'utente viene invitato nel browser ad autorizzare (una tantum).
  3. L'agente riceve un access_token (con scope limitato, a durata determinata).
  4. Le richieste successive portano il bearer JWT.

Scope per strumento

Limita un agente alla sola lettura, a una carta specifica o a un sottoinsieme di strumenti passando scope= al momento della registrazione. Esempi:

scope=read           # list & get only, no writes
scope=cards:write    # manage cards but not withdraw
scope=card:card_8f3a91b7c4d2  # single card

SDK & esempi

Gli SDK ufficiali sono in arrivo. Nel frattempo, l'API è una superficie REST piatta — qualsiasi client HTTP moderno è compatibile.

Node.js (fetch)

const res = await fetch('https://api.cryptocardium.com/v1/cards', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.CCM_KEY}`,
    'Idempotency-Key': `card_${crypto.randomUUID()}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    type: 'virtual', bin: '489517', load_usd: 300
  })
});
const card = await res.json();

Python (requests)

import requests, os, uuid

r = requests.post(
    'https://api.cryptocardium.com/v1/cards',
    headers={
        'Authorization': f"Bearer {os.environ['CCM_KEY']}",
        'Idempotency-Key': f"card_{uuid.uuid4()}",
    },
    json={'type': 'virtual', 'bin': '489517', 'load_usd': 300}
)
card = r.json()

PHP (curl)

$ch = curl_init('https://api.cryptocardium.com/v1/cards');
curl_setopt_array($ch, [
    CURLOPT_POST => 1,
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . $_ENV['CCM_KEY'],
        'Idempotency-Key: card_' . bin2hex(random_bytes(16)),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'type' => 'virtual',
        'bin' => '489517',
        'load_usd' => 300,
    ]),
]);
$card = json_decode(curl_exec($ch), true);

Changelog

Le modifiche additive vengono distribuite in modo trasparente. Le modifiche che introducono incompatibilità vengono inserite sotto un nuovo prefisso di versione.

  • 2026-05-19 · v1.4 Aggiunto

    POST /v1/cards/:id/load & /unload sono ora atomici. Aggiunto l'evento webhook card.loaded.

  • 2026-05-18 · v1.3 Aggiunto

    Server MCP attivo su mcp.cryptocardium.com. OAuth 2.1 DCR. Oltre 40 strumenti mappati da REST.

  • 2026-05-17 · v1.2 Aggiunto

    Programma carta fisica Gold (BIN 448585), 3-D Secure su Visa Business e Visa Gold.

  • 2026-05-15 · v1.1 Modificato

    Importo minimo di ricarica ridotto a $20 per il routing sandbox, $200 per le rotte in produzione.

  • 2026-05-12 · v1.0 Rilasciato

    v1 LTS. Oltre 50 endpoint. Autenticazione Bearer + chiavi di idempotenza + webhook HMAC.

Supporto

Hai bisogno di aiuto? Due percorsi disponibili:

Includi il request_id dalla risposta d'errore — riduce i tempi di risoluzione di 10 volte.

FAQ

Domande per sviluppatori.

Everything people actually ask. Last updated .

Dove si trova la specifica OpenAPI?

OpenAPI 3.1 è disponibile su https://cryptocardium.com/openapi.json (JSON) e /openapi.yaml. Collegata dalla homepage tramite rel="service-desc".

Come vengono autenticate le richieste?

Tre opzioni: (1) Bearer di sessione dal login, (2) chiave API bearer creata su /api-settings, (3) token di accesso OAuth 2.1 (consigliato per agenti AI, supporta Dynamic Client Registration). Tutti e tre vengono inviati nell'intestazione Authorization.

Qual è il limite di velocità?

600 richieste al minuto per chiave API, con un burst di 100 richieste. Le intestazioni X-RateLimit-Limit / X-RateLimit-Remaining / X-RateLimit-Reset vengono restituite in ogni risposta. Limiti superiori disponibili su richiesta tramite /contact.

Come funziona l'idempotenza?

Passa un'intestazione Idempotency-Key (qualsiasi UUID o stringa casuale di 32 byte) su POST e PATCH. I tentativi identici entro 24 ore restituiscono la risposta memorizzata nella cache. Payload diversi con la stessa chiave restituiscono 409 Conflict.

Come vengono restituiti gli errori?

Ogni risposta non-2xx è { "error": "machine_readable_code", "message": "Leggibile dall'utente", "request_id": "req_..." }. Il codice errore è l'identificatore canonico leggibile dalla macchina; mappa la logica del tuo client su quello, non sul messaggio.

Esistono SDK client?

Esempi di codice in cURL, JavaScript (Node + Fetch) e Python sono inclusi nella documentazione. Gli SDK ufficiali sono distribuiti tramite l'organizzazione GitHub; gli SDK della community sono collegati da /api.

Esiste un ambiente sandbox?

Sì. Usa una chiave API di test da /api-settings (con prefisso sk_test_). Tutti gli endpoint sono replicati; le carte emesse in sandbox non transitano su rail card reali.