CryptoPayIn
Documentazione per sviluppatori

Crea pagamenti che si liquidano on-chain.

Tutto il necessario per creare un pagamento, indirizzare un cliente al checkout ospitato, seguire le conferme ed elaborare i webhook firmati in produzione.

URL di base dell'APIVersione 1
https://cryptopayin.com/v1
ProtocolloREST / JSON
AutenticazioneSecret Bearer
ModalitàSolo live
Introduzione

Un'unica API, un unico flusso ospitato

CryptoPayIn valorizza un ordine nella valuta di presentazione selezionata, blocca istantanee verificate fiat/USD e crypto/USD, assegna un indirizzo di deposito dedicato e monitora i propri nodi blockchain in attesa del pagamento. La contabilità interna, le commissioni e i saldi restano in USD. Il tuo backend riceve subito un URL di checkout e, in seguito, gli eventi firmati del ciclo di vita.

URL di base/v1
Importi fiatUnità minori ISO
Valori cryptoStringhe decimali
Scadenza predefinita30 minuti
!

Questa è un'API live. Non esiste un prefisso sandbox. Ogni creazione riuscita assegna un indirizzo on-chain reale. Per i test end-to-end utilizza un importo ridotto in una valuta supportata e conserva le chiavi segrete sul tuo server.

Come si compone l'integrazione

1Crea una chiave

Genera una chiave segreta una sola volta in Dashboard -> Sviluppatori.

2Crea il pagamento

Invia con POST la valuta dell'ordine, l'importo e l'asset selezionato.

3Apri il checkout

Indirizza il cliente all'URL ospitato restituito.

4Elabora l'evento

Verifica l'HMAC e aggiorna il tuo ordine in modo idempotente.

Per iniziare

Crea il tuo primo pagamento

Genera una chiave API nella dashboard dell'esercente, salva la chiave segreta in una variabile d'ambiente, quindi crea un pagamento dal tuo backend. L'esempio utilizza ETH, così puoi testarlo senza dover scegliere una rete per il token.

curl --request POST https://cryptopayin.com/v1/payments \
  --header "Authorization: Bearer $CPI_SECRET_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: order_1042" \
  --data '{
    "amount": 49.99,
    "currency": "USD",
    "asset": "ETH",
    "order_ref": "order_1042",
    "redirect_url": "https://shop.example/orders/1042/paid"
  }'

Usa la risposta

Conserva id del pagamento insieme al tuo ordine, poi reindirizza il cliente a checkout_url. Non calcolare tu stesso un importo in crypto o un indirizzo di deposito.

{
  "id": "P-9F27C1E4KD",
  "object": "payment",
  "status": "created",
  "amount": 49.99,
  "amount_decimal": "49.99",
  "amount_minor": 4999,
  "currency": "USD",
  "currency_minor_units": 2,
  "amount_usd": 49.99,
  "amount_usd_cents": 4999,
  "fx_rate_usd": "1.000000000000",
  "fx_source": "fixed:USD",
  "fx_observed_at": "2026-07-17T13:00:00+00:00",
  "fx_discrepancy_bps": 0,
  "asset": "ETH",
  "network": "mainnet",
  "crypto_amount": "0.01388612",
  "crypto_received": "0",
  "deposit_address": "0x71b8c3d4700000000000000000000000000084e2",
  "exchange_rate": "3600.00000000",
  "exchange_rate_currency": "USD",
  "exchange_rate_source": "median:cb,cg,cl",
  "exchange_rate_source_count": 3,
  "exchange_rate_observed_at": "2026-07-17T13:00:00+00:00",
  "exchange_rate_discrepancy_bps": 12,
  "confirmations": 0,
  "confirmations_required": 12,
  "order_ref": "order_1042",
  "checkout_url": "https://cryptopayin.com/i/P-9F27C1E4KD",
  "expires_at": "2026-07-17T13:30:00+00:00",
  "created_at": "2026-07-17T13:00:00+00:00",
  "completed_at": null
}
Credenziali

Autenticazione

Ogni richiesta API utilizza la chiave segreta in un header HTTP Bearer. Le chiavi segrete iniziano con csk_live_. Il valore cpk_live_ associato è un identificatore pubblico per la tua dashboard e non deve mai essere utilizzato come credenziale Bearer.

AUTHAuthorization: Bearer csk_live_...Ogni endpoint
Mostrato una sola volta

La chiave segreta in chiaro viene restituita solo al momento della creazione. CryptoPayIn memorizza un hash della password più un indice di ricerca SHA-256, mai il segreto in chiaro.

Chiavi indipendenti

Crea chiavi separate per ogni applicazione o ambiente e revocale in modo indipendente. Un account può avere fino a 50 chiavi attive.

Solo lato server

Non inserire mai un valore csk_live_ in JavaScript lato browser, in un binario mobile, in un repository pubblico o in una pagina di checkout.

Ambito dei webhook

Un endpoint webhook può valere per l'intero account oppure essere associato a una singola chiave API, mantenendo le integrazioni isolate.

i

Una chiave segreta mancante, malformata, revocata o sconosciuta restituisce 401 unauthorized. Un account esercente sospeso o chiuso viene respinto allo stesso modo. Una chiave valida utilizzata al di fuori delle autorizzazioni concesse restituisce 403 insufficient_scope.

Tentativi sicuri

Idempotenza

Invia un Idempotency-Key univoco a ogni creazione di pagamento. Se la connessione cade dopo l'invio, ripeti lo stesso JSON con la stessa chiave: CryptoPayIn restituisce il pagamento originale invece di assegnare un nuovo indirizzo.

CasoRisultatoHTTP
Primo utilizzoCrea e restituisce un nuovo pagamento.201
Stessa chiave + stesso JSONRestituisce il pagamento esistente con Idempotent-Replayed: true.200
Stessa chiave + JSON diversoRifiuta la richiesta come idempotency_conflict.409

Le chiavi sono associate alla credenziale API e possono contenere da 1 a 128 caratteri tra lettere, cifre, punti, trattini bassi, due punti o trattini. Uno UUID d'ordine persistente è una buona scelta. Lo stesso meccanismo protegge anche i prelievi, in modo che un prelievo ripetuto non possa mai spostare i fondi due volte.

API REST

Riferimento API

L'API copre pagamenti, link di pagamento, negozi, prodotti, saldi e prelievi. Le risposte utilizzano JSON UTF-8 su HTTPS; ogni creazione o aggiornamento richiede Content-Type: application/json. Le operazioni di modifica sono soggette alle autorizzazioni della chiave chiamante. Non esiste, intenzionalmente, alcun flusso CORS da browser: le chiamate spettano al tuo backend.

GET/v1/assetsScopri gli asset disponibili
GET/v1/currenciesScopri le valute fiat di presentazione
POST/v1/paymentsCrea un pagamento
GET/v1/paymentsElenca e filtra i pagamenti
GET/v1/payments/{id}Recupera un pagamento
i

La versione 1 può ricevere campi ed endpoint retrocompatibili. Una modifica del contratto con breaking change utilizzerà un nuovo percorso di base, anziché modificare silenziosamente /v1.

API reference

Elenca gli asset

GET/v1/assetsRichiede autenticazione Bearer

Usa questo endpoint come fonte di verità per le scelte di checkout. Restituisce le voci di catalogo abilitate, i tassi attuali verificati in modo indipendente, gli importi minimi equivalenti in USD e se il nodo e il feed dei prezzi sono pronti. Una voce può restare elencata con available: false mentre un nodo è in fase di sincronizzazione o il suo prezzo non può essere verificato.

curl https://cryptopayin.com/v1/assets \
  --header "Authorization: Bearer $CPI_SECRET_KEY"
{
  "object": "list",
  "data": [{
    "asset": "USDT",
    "network": "TRC20",
    "type": "token",
    "decimals": 6,
    "minimum_amount": 1,
    "currency": "USD",
    "base_confirmations": 19,
    "available": true,
    "rate_usd": "1.00000000",
    "rate_source": "median:cb,cg,cl",
    "rate_source_count": 3,
    "rate_discrepancy_bps": 4,
    "rate_status": "healthy",
    "rate_updated_at": "2026-07-17T13:00:00+00:00"
  }]
}

Identificatori di catalogo e di rete

AssetValore di reteAbbreviazioneConferme di base
BTCmainnetBTC2
ETHmainnetETH6
USDTTRC20 / ERC20USDT.TRC2019 / 6
USDCERC20USDC.ERC206
DAIERC20DAI6
SHIBERC20SHIB6
PEPEERC20PEPE6
LTCmainnetLTC6
TRXmainnetTRX19
DOGEmainnetDOGE20
XMRmainnetXMR10
SOLmainnetSOL32
!

La disponibilità è dinamica. Non codificare in modo statico la tabella precedente come allow-list live. Per i simboli multi-rete come USDT, invia esplicitamente network oppure utilizza l'abbreviazione ASSET.NETWORK.

API reference

Elenca le valute fiat

GET/v1/currenciesRichiede autenticazione Bearer

Restituisce le valute di presentazione abilitate, la loro precisione ISO e lo stato attuale della conversione in USD. Proponi solo le righe con available: true. L'USD è intrinseco; ogni altra valuta richiede una quotazione live aggiornata e una verifica di riferimento indipendente. minimum_amount converte in quella valuta la soglia minima configurata tra gli asset abilitati; l'asset scelto può richiedere un importo più alto, quindi leggi sempre anche GET /v1/assets.

curl https://cryptopayin.com/v1/currencies \
  --header "Authorization: Bearer $CPI_SECRET_KEY"
{
  "object": "list",
  "accounting_currency": "USD",
  "data": [{
    "currency": "EUR",
    "name": "Euro",
    "symbol": "€",
    "minor_units": 2,
    "available": true,
    "minimum_amount": "0.86",
    "rate_usd": "1.160000000000",
    "rate_source": "coinbase+ecb",
    "rate_source_count": 2,
    "rate_discrepancy_bps": 18,
    "rate_updated_at": "2026-07-17T13:00:00+00:00",
    "rate_reference_at": "2026-07-16T00:00:00+00:00"
  }]
}
i

La valuta omessa su POST /v1/payments significa comunque USD per compatibilità con le versioni precedenti. Le valute a zero decimali come JPY rifiutano importi frazionari. Considera i minimi e i tassi di catalogo come dati live, mai come costanti fisse.

API reference

Crea un pagamento

POST/v1/payments120 richieste / minuto / chiave

Crea una fattura nella valuta di presentazione richiesta, blocca istantanee fiat/USD e crypto/USD verificate e aggiornate, calcola l'importo esatto in crypto e associa un indirizzo di deposito on-chain dedicato.

Corpo della richiesta

CampoTipoRequisitoDescrizione
amountnumero o stringa decimaleobbligatorioValore in currency, alla precisione ISO di quella valuta. Il suo equivalente in USD bloccato non deve superare $1,000,000.00; si applicano anche gli importi minimi per asset.
currencystringafacoltativoValuta a 3 lettere abilitata da GET /v1/currencies. Il valore predefinito è USD.
assetstringaobbligatorioSimbolo come ETH, oppure abbreviazione come USDT.TRC20.
networkstringacondizionaleObbligatorio quando un simbolo esiste su più reti. Esempio: ERC20.
order_refstringafacoltativoIl tuo identificatore d'ordine, massimo 128 caratteri. Restituito nelle risposte e negli eventi dell'API.
customer_emailstringafacoltativoIndirizzo email valido, massimo 190 caratteri. Salvato con il record di pagamento dell'esercente.
redirect_urlstringafacoltativoURL HTTPS, massimo 255 caratteri, proposto dopo un checkout riuscito.

Campi della risposta

CampoTipoDescrizione
idstringaIdentificatore stabile del pagamento, che inizia con P-.
statusstringaStato attuale del ciclo di vita.
amount / amount_decimal / amount_minornumero / stringa / interoValore di presentazione richiesto, espresso in forma comoda, decimale esatta e in unità minori ISO.
currency / currency_minor_unitsstringa / interoValuta di presentazione bloccata e la sua precisione.
amount_usd / amount_usd_centsnumero / interoValore contabile interno in USD, immutabile.
fx_rate_usd / fx_source / fx_observed_atstringa decimale / stringa / ISO 8601Istantanea bloccata del tasso USD per unità di presentazione e i relativi metadati di audit.
asset / networkstringaAsset on-chain risolto.
crypto_amountstringa decimaleImporto esatto che il cliente deve inviare. Non interpretare mai i decimali delle crypto come numeri in virgola mobile binari.
crypto_receivedstringa decimaleTotale attualmente osservato all'indirizzo di deposito.
deposit_addressstringaIndirizzo dedicato assegnato a questo pagamento.
exchange_ratestringa decimaleTasso crypto/USD bloccato, usato per calcolare crypto_amount; questo campo mantiene il suo significato originale della v1.
exchange_rate_source / exchange_rate_observed_atstringa / ISO 8601Istantanea di audit immutabile del tasso crypto.
confirmationsinteroConferme di rete attuali.
confirmations_requiredinteroSoglia per questo pagamento. Fasce USD più alte possono richiedere conferme aggiuntive.
checkout_urlURLFattura ospitata da mostrare al cliente.
expires_atISO 8601Scadenza per una fattura non pagata.
completed_atISO 8601 / nullOrario di liquidazione finale a completamento avvenuto.

Entrambe le conversioni live vengono validate per aggiornamento, numero di fonti e divergenza prima della creazione. Se la verifica fallisce, la creazione restituisce un errore invece di utilizzare un tasso non aggiornato. L'importo in crypto viene arrotondato per eccesso alla precisione utile per l'asset, così l'arrotondamento non lascia mai l'esercente in perdita.

API reference

Elenca i pagamenti

GET/v1/payments240 richieste / minuto / chiave

Restituisce prima i pagamenti più recenti per l'account esercente autenticato. Usa la paginazione a cursore per la riconciliazione e filtri esatti per individuare un ordine senza scorrere l'intera cronologia.

Parametri di query

ParametroPredefinitoDescrizione
limit20Dimensione della pagina da 1 a 100.
starting_afterID del pagamento restituito come next_cursor della pagina precedente.
statusStato esatto del ciclo di vita, ad esempio pending, completed o expired.
order_refRiferimento esatto dell'ordine dell'esercente, massimo 128 caratteri.
curl "https://cryptopayin.com/v1/payments?status=completed&limit=20" \
  --header "Authorization: Bearer $CPI_SECRET_KEY"
{
  "object": "list",
  "data": [{
    "id": "P-9F27C1E4KD",
    "object": "payment",
    "status": "completed",
    "amount": 49.99,
    "currency": "USD",
    "asset": "ETH",
    "network": "mainnet",
    "crypto_amount": "0.01388612",
    "crypto_received": "0.01388612",
    "order_ref": "order_1042",
    "confirmations": 12,
    "confirmations_required": 12,
    "completed_at": "2026-07-17T13:12:42+00:00"
  }],
  "has_more": true,
  "next_cursor": "P-9F27C1E4KD"
}
i

Quando has_more è true, trasmetti next_cursor invariato come starting_after. I parametri di query sconosciuti o ripetuti in stile array vengono rifiutati anziché ignorati.

API reference

Recupera un pagamento

GET/v1/payments/{id}240 richieste / minuto / chiave

Restituisce lo stesso oggetto pagamento della creazione, con stato aggiornato, importo ricevuto, hash della transazione e conferme. Una chiave può recuperare solo i pagamenti appartenenti al proprio account esercente.

curl https://cryptopayin.com/v1/payments/P-9F27C1E4KD \
  --header "Authorization: Bearer $CPI_SECRET_KEY"
i

I webhook dovrebbero guidare i normali aggiornamenti dell'ordine. Usa il recupero per riconciliare dopo un timeout, verificare un evento, generare una pagina di stato lato backend o correggere consegne mancate.

Modello di stato

Ciclo di vita del pagamento

Considera sempre lo stato dell'API come autorevole. Non dedurre il completamento da un reindirizzamento del browser o dal fatto che il cliente dichiari di aver pagato.

created->pending->underpaidorconfirming->completed/overpaid
StatoSignificatoAzione dell'esercente
createdFattura e indirizzo assegnati; nessun finanziamento rilevato ancora.Mostra il checkout ospitato.
pendingIn attesa di un pagamento on-chain utilizzabile.Mantieni l'ordine aperto.
underpaidI fondi arrivati sono inferiori alla tolleranza dell'esercente.Chiedi al pagatore di inviare il residuo indicato.
confirmingRilevato un valore sufficiente; in attesa delle conferme.Non evadere ancora l'ordine.
completedRaggiunti il valore richiesto e le conferme.Evadi l'ordine una sola volta.
overpaidÈ stato confermato più del previsto.Evadi l'ordine e verifica l'eccedenza.
expiredNessun pagamento idoneo è stato rilevato prima della scadenza.Crea un nuovo pagamento.
failedAssegnazione dell'indirizzo o elaborazione non riuscita.Registra l'errore e crea un nuovo pagamento.
!

I trasferimenti on-chain sono irreversibili e CryptoPayIn non dispone di un meccanismo di rimborso — un pagamento confermato è definitivo. Qualsiasi restituzione per cortesia commerciale viene gestita direttamente tra te e il tuo cliente, al di fuori della piattaforma.

Esperienza del cliente

Checkout ospitato

Ogni pagamento API include una checkout_url responsive. Mostra l'esercente, l'importo di presentazione richiesto, l'equivalente in USD bloccato quando pertinente, l'importo esatto in crypto, l'indirizzo di deposito, il codice QR, l'avviso di rete, il conto alla rovescia e l'avanzamento delle conferme in tempo reale.

Tasso bloccato

Il cliente vede lo stesso crypto_amount restituito dall'API per la finestra della fattura.

Nessun account cliente

Il pagatore non crea un account CryptoPayIn né condivide credenziali.

Stato in tempo reale

La pagina interroga il pagamento in modo sicuro e passa da in attesa a in conferma a pagato.

Reindirizzamento dell'esercente

Un redirect_url HTTPS viene proposto dopo il successo; non costituisce prova di pagamento.

i

Mantieni l'evasione sul tuo backend. La navigazione del browser può essere abbandonata, ripetuta o falsificata; solo un webhook verificato o una GET autenticata dimostrano lo stato del pagamento.

Credenziali

Autorizzazioni & scope

Ogni chiave API porta con sé un insieme fisso di autorizzazioni scelte al momento della creazione in Dashboard → Sviluppatori. Ogni endpoint verifica gli scope della chiave prima di eseguire qualsiasi operazione; una chiamata al di fuori del permesso concesso a una chiave restituisce 403 insufficient_scope con un header X-Required-Scope che indica l'autorizzazione mancante. Gli scope vengono impostati una sola volta alla creazione e non possono essere ampliati in seguito — genera invece una nuova chiave. Le chiavi create prima dell'esistenza degli scope mantengono esattamente la loro capacità originale: payments:read e payments:write.

ScopeConcedeEndpoint
payments:readElenca e recupera i pagamentiGET /v1/payments, GET /v1/payments/{id}
payments:writeCrea pagamenti ospitatiPOST /v1/payments
links:readElenca e recupera i link di pagamentoGET /v1/links, GET /v1/links/{id}
links:writeCrea, modifica, sospendi ed elimina i link di pagamentoPOST/PATCH/DELETE /v1/links
shops:readElenca e recupera i negozi e i relativi prodottiGET /v1/shops, GET .../products
shops:writeCrea e modifica negozi, prodotti e variantiPOST/PATCH/DELETE /v1/shops e prodotti
balance:readLegge i saldi in crypto e le stime in USDGET /v1/balance
payouts:readElenca e recupera i prelieviGET /v1/payouts, GET /v1/payouts/{id}
payouts:writeRichiede prelievi on-chainPOST /v1/payouts
!

payouts:write sposta fondi on-chain ed è irreversibile. Concedilo solo a chiavi di cui ti fidi pienamente, mantieni quelle chiavi lato server e preferisci una chiave dedicata per ogni processo automatizzato. GET /v1/account restituisce gli scope della chiave chiamante e i limiti del tuo account.

Acquirenti automatizzati

Checkout agenti

Ogni link di pagamento attivo è anche un checkout leggibile dalle macchine: un agente IA o qualsiasi script può scoprirlo, creare una fattura e leggere la consegna senza un browser — e senza alcuna chiave API, perché si tratta di endpoint pubblici per l'acquirente sul dominio del link, non di endpoint per l'esercente. Contratto completo ed esempio pratico: cryptopayin.com/agents.

GEThttps://cryptopaylink.co/pay/{link}.jsonpubblico · discovery

Restituisce lo stato, il prezzo, gli asset accettati e il contratto esatto di input per la chiamata di fatturazione (campi obbligatori, schema di spedizione, varianti).

POSThttps://cryptopaylink.co/pay/{link}/invoicepubblico · supporta Idempotency-Key

Crea la fattura utilizzando lo stesso nucleo, la stessa istantanea dei prezzi e gli stessi limiti anti-abuso della pagina ospitata, e restituisce l'indirizzo di deposito, l'importo esatto in crypto, un URI del wallet e l'URL della ricevuta. L'agente paga quindi on-chain da qualsiasi wallet che controlla.

GEThttps://cryptopaylink.co/pay/{link}/receipt?p={payment}pubblico · polling ogni 5–10 s

Stato e conferme in tempo reale; una volta completato il pagamento, la risposta include la consegna — il tuo contenuto testuale, l'URL privato o una chiave di licenza riservata a quel pagamento — oltre al tuo messaggio di successo e all'URL di reindirizzamento.

I negozi parlano lo stesso protocollo

Le vetrine espongono lo stesso identico flusso sul proprio dominio: il catalogo con lo stock in tempo reale, poi un'unica chiamata che convalida il carrello, riserva lo stock e restituisce la fattura.

GEThttps://shopycrypto.com/s/{shop}.jsonpubblico · catalogo
POSThttps://shopycrypto.com/s/{shop}/orderpubblico · carrello → fattura, supporta Idempotency-Key
GEThttps://shopycrypto.com/s/{shop}/o/{order}/receipt?p={payment}pubblico · polling ogni 5–10 s

Controlli per il venditore

Il checkout agenti è attivo per impostazione predefinita e costa la stessa commissione fissa dell'1%. Disattivalo per l'intero account in Dashboard → Impostazioni → Generali → IA & checkout agenti: gli endpoint automatizzati su link e negozi risponderanno quindi 403 agents_disabled mentre le tue pagine di checkout per utenti umani continueranno a funzionare. I pagamenti creati dagli agenti non recano alcun contrassegno speciale — sono pagamenti ordinari nella tua dashboard, nei webhook e nelle esportazioni.

Risorse per l'esercente

Negozi

Una vetrina ospitata che raggruppa i prodotti sotto un'unica pagina brandizzata. Un account può avere fino a 10 negozi. I prodotti si gestiscono tramite gli endpoint di prodotto annidati riportati di seguito.

GET/v1/shopsshops:read
POST/v1/shopsshops:write
GET/v1/shops/{id}shops:read
PATCH/v1/shops/{id}shops:write
DELETE/v1/shops/{id}shops:write

Corpo della richiesta

CampoTipoRequisitoDescrizione
namestringaobbligatorio2–80 caratteri.
taglinestringafacoltativoFino a 160 caratteri.
themestringafacoltativolight (predefinito) o dark.
accentstringafacoltativoColore accento esadecimale dalla palette del negozio, restituito come accent_palette su GET /v1/shops.
accepted_assetsarray di stringhefacoltativoAsset predefiniti per i prodotti del negozio, ad es. ["BTC","LTC","XMR"]. Applicati a tutti i prodotti quando modificati.
statusstringafacoltativoSolo PATCH: active o paused.
i

Un negozio disabilitato da CryptoPayIn per motivi di policy non può essere riattivato né eliminato tramite l'API e restituisce admin_disabled (403). L'eliminazione di un negozio rimuove i relativi prodotti; i pagamenti passati restano invariati.

Risorse per l'esercente

Prodotti & varianti

I prodotti risiedono all'interno di un negozio. Ogni negozio può avere fino a 50 prodotti. Un prodotto può essere digitale (con consegna istantanea) o fisico (con paesi di spedizione), e può esporre fino a 30 combinazioni di varianti costruite da 1–3 gruppi di opzioni.

GET/v1/shops/{shop}/productsshops:read
POST/v1/shops/{shop}/productsshops:write
GET/v1/shops/{shop}/products/{id}shops:read
PATCH/v1/shops/{shop}/products/{id}shops:write
DELETE/v1/shops/{shop}/products/{id}shops:write

Corpo della richiesta

CampoTipoRequisitoDescrizione
titlestringaobbligatorio3–120 caratteri.
description / blurbstringafacoltativoDescrizione completa e una riga per la scheda del negozio di massimo ≤200 caratteri.
emojistringafacoltativoSingola emoji mostrata sulla scheda del prodotto.
featuredbooleanofacoltativoAl massimo un prodotto in evidenza per negozio.
product_typestringafacoltativodigital (predefinito) o physical.
shipping_countriesarray di stringhecondizionaleSolo prodotti fisici: codici ISO come ["FR","BE"], oppure ["*"] per la spedizione mondiale.
amount_type / currency / amount / min / maxmistocondizionalePrezzo di base, con le stesse regole dei link di pagamento. I prodotti fisici devono essere fixed.
max_usesinterofacoltativoLimite totale di vendite (0 = illimitato).
delivery_type + delivery_text/url/keysmistofacoltativoConsegna digitale per il prodotto base, con lo stesso formato dei link di pagamento.
variant_optionsarrayfacoltativo1–3 gruppi {name, values[]}, ciascuno con 2–10 valori. Le combinazioni non devono superare 30.
variantsarraycondizionaleUn oggetto per combinazione (vedi sotto). Obbligatorio ed esaustivo quando è presente variant_options.
statusstringafacoltativoSolo PATCH: active o paused.

Oggetto variante

CampoTipoDescrizione
optionsarray di stringheUn valore per gruppo di opzioni, nell'ordine dei gruppi, ad es. ["Pro","Lifetime"].
pricenumero o stringaPrezzo della variante nella valuta del prodotto.
stockintero o nullUnità rimanenti, oppure null per illimitato.
delivery_type + delivery_text/url/keysmistoOverride opzionale della consegna digitale per singola variante (inherit per impostazione predefinita). Le chiavi devono essere univoche nell'intero prodotto.
curl -X POST https://cryptopayin.com/v1/shops/SH-JYRK8TFJ/products \
  -H "Authorization: Bearer $CPI_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Software license",
    "amount": 30,
    "currency": "USD",
    "variant_options": [
      {"name": "Edition", "values": ["Standard", "Pro"]},
      {"name": "Term", "values": ["1 year", "Lifetime"]}
    ],
    "variants": [
      {"options": ["Standard","1 year"], "price": 30, "delivery_type": "keys", "delivery_keys": ["S1Y-1"]},
      {"options": ["Standard","Lifetime"], "price": 79, "stock": 10, "delivery_type": "keys", "delivery_keys": ["SLT-1"]},
      {"options": ["Pro","1 year"], "price": 59, "delivery_type": "keys", "delivery_keys": ["P1Y-1"]},
      {"options": ["Pro","Lifetime"], "price": 149, "stock": 5, "delivery_type": "keys", "delivery_keys": ["PLT-1"]}
    ]
  }'
i

PATCH preserva gli ordini esistenti e le chiavi già consegnate. Per modificare prezzi o stock, invia nuovamente l'array variants corrispondente; le combinazioni che ometti vengono messe in pausa se hanno ordini, altrimenti rimosse. Un prodotto può contenere al massimo 10,000 chiavi di licenza attive tra base e varianti, e ogni chiave deve essere univoca all'interno del prodotto.

Risorse per l'esercente

Saldo

GET/v1/balancebalance:read

Restituisce i tuoi saldi crypto liquidati per asset, con una stima in USD su base best-effort e la commissione di rete addebitata su un prelievo. La contabilità interna è sempre in USD; i saldi maturano dai pagamenti completati al netto della commissione dell'esercente.

{
  "object": "list",
  "accounting_currency": "USD",
  "minimum_payout_usd": 25,
  "data": [{
    "asset": "USDT",
    "network": "TRC20",
    "amount": "99.099",
    "usd_estimate": 99.02,
    "payout_network_fee": "2.445463"
  }]
}
i

usd_estimate è null quando un tasso live verificato non è momentaneamente disponibile; il saldo sottostante resta comunque esatto. Usa questi valori per decidere i prelievi, non per la contabilità definitiva.

Risorse per l'esercente

Prelievi

Sposta la crypto liquidata verso un wallet esterno. I prelievi sono irreversibili, quindi questo endpoint applica tutte le stesse protezioni della dashboard: una destinazione valida per l'asset, un tasso live verificato, il minimo dell'account, un saldo sufficiente comprensivo della commissione di rete e la conferma a due fattori quando l'account ha la 2FA attiva.

GET/v1/payoutspayouts:read
POST/v1/payoutspayouts:write · 30 / min / chiave
GET/v1/payouts/{id}payouts:read

Corpo della richiesta

CampoTipoRequisitoDescrizione
assetstringaobbligatorioSimbolo o abbreviazione, ad es. LTC o USDT.TRC20.
networkstringacondizionaleObbligatorio quando il simbolo esiste su più reti.
amountnumero o stringaobbligatorioImporto da inviare, esclusa la commissione di rete, alla precisione dell'asset. Il suo controvalore in USD deve rispettare il minimo dell'account.
addressstringaobbligatorioIndirizzo di destinazione, validato per la chain dell'asset.
notestringafacoltativoRiferimento personale, fino a 255 caratteri.
totp_codestringacondizionaleCodice attuale a 6 cifre o codice di recupero. Obbligatorio quando la 2FA è attiva sull'account.
curl -X POST https://cryptopayin.com/v1/payouts \
  -H "Authorization: Bearer $CPI_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: withdraw-2026-07-19-01" \
  -d '{
    "asset": "USDT.TRC20",
    "amount": "50",
    "address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
    "note": "weekly settlement"
  }'
{
  "id": "W-EM64ZCJB",
  "object": "payout",
  "status": "requested",
  "asset": "USDT",
  "network": "TRC20",
  "amount": "50",
  "fee": "2.445463",
  "total_debited": "52.445463",
  "address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
  "txid": null,
  "confirmations": 0,
  "created_at": "2026-07-19T19:10:00+00:00"
}

Ciclo di vita dello stato

StatoSignificato
requestedRiservato dal tuo saldo; in attesa di revisione da parte dell'operatore o di approvazione automatica.
approved / processingAutorizzato e in coda per la trasmissione da parte dell'esecutore.
sentTrasmesso on-chain; txid è valorizzato.
confirmedHa raggiunto le conferme richieste. Definitivo.
failedNon è stato possibile inviarlo; failure_message spiega il motivo e il saldo viene restituito.
cancelledAnnullato prima della trasmissione; il saldo riservato viene restituito.

Invia un Idempotency-Key in modo che un nuovo tentativo di rete non possa mai creare un secondo prelievo: la stessa chiave con lo stesso corpo restituisce il prelievo originale (Idempotent-Replayed: true); la stessa chiave con un corpo diverso restituisce 409 idempotency_conflict. Il codice 2FA è deliberatamente escluso dall'impronta di idempotenza, così un codice che cambia non genera un falso conflitto. La riserva addebita subito il tuo saldo; un prelievo fallito o annullato lo restituisce.

Risorse per l'esercente

Account

GET/v1/accountqualsiasi chiave valida

Restituisce il profilo del tuo account, gli scope della chiave chiamante, la tua commissione di piattaforma e tutti i limiti live — utile per un'integrazione auto-configurante o un controllo preliminare.

{
  "object": "account",
  "id": "MC67T3PHQZ",
  "fee_bps": 100,
  "fee_percent": 1,
  "default_currency": "USD",
  "two_factor_enabled": false,
  "api_key": {"label": "production", "scopes": ["payments:read","payments:write"]},
  "limits": {
    "shops": {"used": 1, "max": 10},
    "payment_links": {"used": 0, "max": 50},
    "products_per_shop_max": 50,
    "variant_combinations_per_product_max": 30,
    "license_keys_per_product_max": 10000,
    "active_api_keys_max": 50,
    "checkout_fields_per_link_max": 5
  },
  "minimum_payout_usd": 25
}
Eventi server-to-server

Webhook

Aggiungi fino a 10 endpoint HTTPS pubblici in Dashboard -> Sviluppatori. Ogni endpoint riceve un proprio segreto di firma whsec_..., mostrato una sola volta. Può ascoltare per l'intero account oppure essere associato a una specifica chiave API attiva; gli endpoint associati a una chiave ricevono solo i pagamenti creati con quella chiave.

Verifica prima di eseguire il parsing

CryptoPayIn firma il corpo grezzo esatto della richiesta utilizzando il segreto dell'endpoint. La versione 1 firma timestamp + "." + raw_body. Rifiuta i timestamp non aggiornati prima di accettare l'evento.

import crypto from "node:crypto";

const timestamp = req.headers["x-cpi-timestamp"];
const signature = req.headers["x-cpi-signature"];
const rawBody = req.rawBody; // Buffer captured before JSON parsing

if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
  throw new Error("stale webhook");
}
const expected = "sha256=" + crypto
  .createHmac("sha256", process.env.CPI_WEBHOOK_SECRET)
  .update(Buffer.concat([Buffer.from(`${timestamp}.`), rawBody]))
  .digest("hex");
const valid = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
if (!valid) throw new Error("invalid webhook signature");

Header di consegna

HeaderEsempioScopo
Content-Typeapplication/jsonCorpo JSON UTF-8.
X-CPI-Timestamp1784293200Secondi Unix inclusi nel messaggio firmato.
X-CPI-Signaturesha256=...HMAC-SHA256 esadecimale.
X-CPI-Signature-Versionv1Versione dello schema di firma.
X-CPI-Event-Idevt_a12b...ID logico stabile dell'evento; identico tra i vari tentativi.
X-CPI-Delivery-Id1842ID stabile del record di consegna dell'endpoint.

Payload del pagamento

{
  "event_id": "evt_a12b34c56d78e90f12345678",
  "event": "payment.completed",
  "id": "P-9F27C1E4KD",
  "status": "completed",
  "order_ref": "order_1042",
  "amount": 49.99,
  "amount_decimal": "49.99",
  "amount_minor": 4999,
  "currency_minor_units": 2,
  "currency": "USD",
  "amount_usd": 49.99,
  "amount_usd_cents": 4999,
  "fx_rate_usd": "1.000000000000",
  "fx_source": "fixed:USD",
  "fx_observed_at": "2026-07-17T13:00:00Z",
  "fx_discrepancy_bps": 0,
  "exchange_rate": "3600.00000000",
  "exchange_rate_currency": "USD",
  "exchange_rate_source": "median:cb,cg,cl",
  "exchange_rate_source_count": 3,
  "exchange_rate_observed_at": "2026-07-17T13:00:00Z",
  "exchange_rate_discrepancy_bps": 12,
  "asset": "ETH",
  "network": "mainnet",
  "crypto_amount": "0.01388612",
  "crypto_received": "0.01388612",
  "txid": "0x9d81...75af",
  "confirmations": 12,
  "confirmations_required": 12,
  "deposit_address": "0x71b8c3d4700000000000000000000000000084e2",
  "sent_at": "2026-07-17T13:12:42Z"
}

Tentativi e sicurezza dell'endpoint

Restituisci un qualsiasi 2xx

Una consegna ha esito positivo con HTTP 200-299. Esegui le operazioni onerose in modo asincrono e rispondi rapidamente.

Sei tentativi totali

Il corpo esatto e l'ID evento vengono conservati; in caso di errore, i tentativi vengono ripetuti dopo circa 1 minuto, 5 minuti, 30 minuti, 2 ore e 6 ore.

Nessun reindirizzamento

Le risposte 3xx non vengono seguite. Registra direttamente l'URL HTTPS finale.

Solo destinazioni pubbliche

Gli IP privati, loopback, link-local e riservati sono bloccati; ogni risposta DNS viene convalidata e la connessione è soggetta a pinning.

!

Le consegne avvengono almeno una volta. Rendi il tuo handler idempotente registrando event_id con un vincolo di unicità prima dell'evasione. Recupera l'oggetto tramite l'API quando riconcili un evento imprevisto.

Webhook

Riferimento eventi

payment.completedValore atteso confermato.
payment.overpaidConfermato più del previsto.
payment.underpaidRilevato un finanziamento inferiore alla tolleranza.
payment.expiredFinestra della fattura non pagata chiusa.
payment.failedConfigurazione o elaborazione del pagamento non riuscita.
payout.sentPrelievo trasmesso on-chain.
payout.confirmedIl prelievo ha raggiunto le conferme.
payout.failedIl prelievo non è andato a buon fine.
webhook.testTest di connettività manuale.

Struttura dell'evento di prelievo

{
  "event_id": "evt_b98c76d54e32a10f87654321",
  "event": "payout.sent",
  "id": "W-8J2K7M4RQP",
  "status": "sent",
  "asset": "ETH",
  "network": "mainnet",
  "amount": "0.25",
  "fee": "0.00081768",
  "address": "0x84f2...9bc1",
  "txid": "0xa1c4...07ee",
  "confirmations": 0,
  "note": "weekly treasury",
  "sent_at": "2026-07-17T14:08:31Z"
}
Affidabilità

Errori e limiti di frequenza

Gli errori utilizzano sempre un unico involucro JSON. Effettua la scelta in base a error.type; il messaggio leggibile può essere migliorato senza un cambio di versione. Cita error.request_id o l'header di risposta X-Request-Id corrispondente quando contatti il supporto.

{
  "error": {
    "type": "ambiguous_asset",
    "message": "specify network (e.g. USDT.ERC20 or USDT.TRC20)",
    "request_id": "b942e21f8dca4b06b8672eb9"
  }
}
HTTPTipi tipiciSignificato
400invalid_request, unknown_parameterJSON, query o header di idempotenza malformati.
401unauthorizedCredenziale/account mancante, non valido o non attivo.
403insufficient_scope, admin_disabledChiave valida priva dell'autorizzazione richiesta (vedi X-Required-Scope), oppure una risorsa bloccata da un amministratore.
404not_foundEndpoint sconosciuto, oppure una risorsa esterna a questo account esercente.
405method_not_allowedUsa il metodo indicato nell'header Allow.
409idempotency_conflictChiave riutilizzata con un JSON diverso.
413request_too_largeIl corpo JSON supera 64 KiB.
415unsupported_media_typeIl corpo della POST non è dichiarato come application/json.
422invalid, limit, invalid_amount, below_minimum, bad_address, 2fa_required, unsupported_assetUna richiesta ben formata non ha superato la validazione deterministica oppure ha raggiunto un limite di risorsa.
429rate_limitedAttendi Retry-After.
500server_errorErrore imprevisto; puoi ritentare in sicurezza con la stessa chiave di idempotenza.
503maintenance, temporarily_unavailable, asset_unavailable, no_rate, price_stale, fiat_rate_unavailable, fiat_rate_stale, derive_failedErrore transitorio della piattaforma, del nodo, del prezzo o dell'assegnazione dell'indirizzo. Non viene sostituita alcuna conversione non aggiornata.

Limiti attuali

AmbitoLimiteFinestra
Tetto di sicurezza Nginx per IP10 richieste/secondo, burst 30Continuo
Tetto per IP non autenticato300 richieste60 secondi
POST /v1/payments, links, shops, products120 richieste per chiave API60 secondi
POST /v1/payouts30 richieste per chiave API60 secondi
Endpoint GET240 richieste per chiave API60 secondi

Limiti dell'account

RisorsaLimite
Negozi per account10
Link di pagamento per account50
Prodotti per negozio50
Combinazioni di varianti per prodotto30
Chiavi di licenza per prodotto / link10,000
Domande di checkout per link5
Chiavi API attive per account50

Consulta il tuo utilizzo in tempo reale rispetto a questi limiti da GET /v1/account.

Le risposte con esito positivo ma limitate a livello applicativo espongono X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset. Ritenta su 429, 500 e 503 con backoff esponenziale e jitter. Per le richieste POST, riutilizza sempre la Idempotency-Key originale e lo stesso JSON.

Sicurezza in produzione

Sicurezza dell'integrazione

Conserva i segreti API in un secret manager

Caricali a runtime; non registrarne mai il valore completo nei log né includerli nel controllo di versione.

Chiama l'API dal tuo backend

Un client browser o mobile non può conservare in sicurezza un segreto dell'esercente.

Verifica il corpo grezzo del webhook

Controlla l'aggiornamento del timestamp e utilizza un confronto della firma a tempo costante prima del parsing JSON.

Rendi l'evasione idempotente

Registra gli eventi/ordini elaborati in modo transazionale, così i tentativi ripetuti non spediscono mai due volte.

Fidati dello stato finale dell'API, non dei redirect

Recupera il pagamento quando un evento è inatteso o il tuo stato locale non coincide.

Ruota per sovrapposizione

Crea una chiave sostitutiva, distribuiscila, verifica il traffico, quindi elimina la vecchia chiave.

!

L'accesso all'account è controllato da una chiave esercente a 16 cifre non recuperabile, protetta facoltativamente da TOTP. Conserva sia l'accesso dell'esercente sia i segreti API con la stessa cura riservata alle credenziali del wallet.

Lancio

Checklist di go-live

1
Crea una chiave API di produzione dedicata

Non riutilizzare la copia personale di uno sviluppatore su più servizi.

2
Interroga entrambi i cataloghi live

Usa GET /v1/assets e GET /v1/currencies; mostra solo le voci presenti e available: true.

3
Aggiungi e testa il tuo endpoint webhook

Salva il segreto di firma una sola volta; verifica timestamp e firma, quindi deduplica l'ID evento stabile.

4
Usa una chiave di idempotenza per ogni ordine

Esegui un tentativo duplicato e conferma che esista un solo ID pagamento.

5
Testa interruzioni dei tassi, pagamenti insufficienti e scadenze

Lo stato del tuo ordine deve restare sicuro anche in presenza di tassi fiat non aggiornati, asset non disponibili, conferme in ritardo e ogni percorso non ideale.

6
Riconcilia quotidianamente

Confronta i tuoi ordini con gli stati di pagamento dell'API, i log dei webhook e il registro dell'esercente.

Pronto per integrare?

Crea un account in pochi secondi, genera una chiave e tieni questo riferimento accanto al tuo codice.

Crea account