Errori
Ogni codice di errore dell'API di Certivant spiegato — forma della risposta, corrispondenza con gli stati HTTP, indicazioni di gestione per ciascun codice e un robusto wrapper per i nuovi tentativi da inserire nella Sua integrazione.
Ogni risposta di errore dell'API di Certivant segue la stessa forma. Scriva un unico gestore degli errori che consumi questa forma, e potrà gestire ogni endpoint in modo uniforme.
Forma della risposta
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Body validation failed.",
"fields": {
"applicant.dateOfBirth": "Invalid date format. Expected YYYY-MM-DD.",
"applicant.nationality": "Must be a 2-character ISO 3166-1 alpha-2 code."
}
}
}
| Campo | Tipo | Note |
|---|---|---|
success | booleano | Sempre false in caso di errore |
error.code | stringa | Leggibile dalla macchina. Usi questo valore per la logica di controllo |
error.message | stringa | Leggibile da una persona. Sicuro da registrare; non sicuro da mostrare direttamente ai richiedenti |
error.fields | oggetto | Presente solo con VALIDATION_ERROR. Associa i percorsi dei campi in notazione a punti ai messaggi di errore per campo |
I testi message degli errori non sono garantiti come stabili tra una versione e l'altra. Usi code per ogni logica; consideri message utile per il log e per lo sviluppo.
Dallo stato HTTP al codice di errore
| HTTP | error.code tipico | Significato |
|---|---|---|
400 | VALIDATION_ERROR | Il corpo della richiesta non ha superato la validazione Zod. Controlli fields |
400 | BAD_REQUEST | Richiesta non valida generica (per esempio inviare prima che siano caricati tutti i documenti) |
401 | UNAUTHORIZED | Chiave API mancante, malformata, revocata o scaduta |
402 | verification_unavailable | L'organizzazione non ha più credito e non è impostata per continuare senza credito |
403 | FORBIDDEN | La chiave è valida ma non ha l'ambito richiesto, proviene da un indirizzo fuori dalla sua lista IP consentiti, è limitata ad altri moduli, oppure la risorsa appartiene a un'altra organizzazione |
404 | NOT_FOUND | La risorsa (req_…, doc_…, ecc.) non esiste o non è visibile all'organizzazione di questa chiave |
409 | CONFLICT | Transizione di stato non consentita (per esempio inviare una richiesta due volte), oppure violazione di un vincolo di unicità (externalRef già in uso) |
413 | BAD_REQUEST | Caricamento di un file superiore a 10 MB |
415 | BAD_REQUEST | Content-Type non supportato per l'endpoint (per esempio un corpo JSON inviato a un endpoint multipart) |
429 | RATE_LIMITED | Superato il limite di frequenza al minuto. Vedi Limiti di frequenza |
500 | INTERNAL_ERROR | Errore imprevisto del server. Sempre registrato dalla nostra parte; riprovare è sicuro |
502 | BAD_GATEWAY | Un servizio a monte (fornitore di sanzioni, gateway di pagamento, registro) non è disponibile. Riprovi dopo una pausa |
503 | SERVICE_UNAVAILABLE | Database degradato. Riprovi con backoff |
Catalogo dei codici di errore
UNAUTHORIZED
La chiave API nell'header Authorization è mancante, malformata o revocata.
{ "success": false, "error": { "code": "UNAUTHORIZED", "message": "Invalid or revoked API key." } }
error.reason indica quale dei casi si verifica: missing_api_key, invalid_api_key, api_key_revoked, api_key_expired oppure api_key_rotated (la chiave è stata ruotata e la sua finestra di sovrapposizione è terminata). L'elenco completo è in Autenticazione.
Come gestirlo: Verifichi che l'header sia Authorization: Bearer ck_live_… (oppure ck_test_…; le chiavi più vecchie iniziano con kyk_). Controlli nella dashboard lo stato della chiave. Se risulta revocata o scaduta, ne crei una nuova oppure la ruoti.
FORBIDDEN
La chiave è valida ma non ha l'ambito richiesto, oppure la risorsa appartiene a un'organizzazione diversa da quella della chiave.
{ "success": false, "error": { "code": "FORBIDDEN", "message": "This API key does not include the kyc:manage scope required for this endpoint." } }
error.reason è insufficient_scope (la chiave non ha un ambito), ip_not_allowed (l'indirizzo del chiamante non è nella lista IP consentiti della chiave) oppure form_not_allowed (la chiave è limitata ad altri moduli).
Come gestirlo: Controlli ambiti e restrizioni della chiave nella dashboard (KYC → Sviluppatore, l'icona della matita). Può modificare i permessi di una chiave, le restrizioni a moduli e workflow, la lista IP consentiti e la scadenza senza cambiarne il segreto; il segreto e l'ambiente (produzione o test) non si possono modificare.
verification_unavailable (HTTP 402)
La Sua organizzazione non ha più credito e non è impostata per continuare senza credito, quindi Certivant non può accettare una nuova verifica. La risposta usa il codice verification_unavailable:
{ "success": false, "error": { "code": "verification_unavailable", "message": "This organization is temporarily unable to accept new verifications. Please contact them to continue." } }
Come gestirlo: Ricarichi il saldo del credito in Impostazioni → Crediti e utilizzo (anche i proprietari e gli amministratori ricevono una notifica e un'email, al massimo una volta al giorno). I richiedenti che incontrano la stessa condizione in un modulo o in una pagina ospitata vedono una pagina che chiede di contattare la Sua organizzazione; la pagina non menziona mai crediti o denaro. Vedi Fatturazione e crediti.
NOT_FOUND
{ "success": false, "error": { "code": "NOT_FOUND", "message": "Request not found." } }
Come gestirlo: Verifichi l'ID della risorsa. Una causa comune è usare un ID di un altro ambiente — gli ID di staging non esistono in produzione e viceversa.
VALIDATION_ERROR
Il corpo della richiesta non ha superato la validazione dello schema. La mappa fields elenca ogni campo non valido con un messaggio per campo.
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Body validation failed.",
"fields": {
"type": "Required",
"applicant.email": "Invalid email format"
}
}
}
Come gestirlo: Mostri fields accanto ai campi del modulo. I percorsi dei campi usano la notazione a punti per i campi annidati e [N] per gli indici degli array (directors[0].dateOfBirth).
BAD_REQUEST
Richiesta non valida generica, che non rientra in altre categorie.
{ "success": false, "error": { "code": "BAD_REQUEST", "message": "Cannot submit a request with pending documents. Upload the remaining documents first." } }
Come gestirlo: Legga il message. Di solito indica un problema di sequenza — chiami prima l'endpoint prerequisito.
CONFLICT
Una transizione di stato non consentita dallo stato attuale, oppure una violazione di un vincolo di unicità.
{ "success": false, "error": { "code": "CONFLICT", "message": "externalRef already in use by request req_…" } }
Come gestirlo: Verifichi lo stato attuale della richiesta tramite GET /requests/:id e si adegui. Per le violazioni di unicità del riferimento, recuperi la richiesta esistente (con ?externalRef=… sull'endpoint di elenco) oppure scelga un altro riferimento.
RATE_LIMITED
{ "success": false, "error": { "code": "RATE_LIMITED", "message": "Rate limit exceeded. Max 120 requests per 60s. Retry in 14s." } }
Le intestazioni di questa risposta includono X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset (secondi prima che il contatore si ricarichi). Vedi Limiti di frequenza per la strategia di nuovo tentativo.
INTERNAL_ERROR
Qualcosa si è rotto dalla nostra parte. Certivant registra ogni errore 500 con il contesto completo.
{ "success": false, "error": { "code": "INTERNAL_ERROR", "message": "An unexpected error occurred. Please try again." } }
Come gestirlo: Riprovi una volta dopo una breve pausa. Se persiste, controlli la pagina di stato e contatti l'assistenza indicando l'ID della richiesta.
BAD_GATEWAY e SERVICE_UNAVAILABLE
Una dipendenza a monte non è disponibile (API del registro commerciale, fornitore di dati sulle sanzioni, storage) oppure il database è degradato.
{ "success": false, "error": { "code": "BAD_GATEWAY", "message": "Sanctions screening provider is unreachable. The request remains in PENDING state — Certivant will retry automatically." } }
Come gestirlo: Li tratti come errori transitori. Implementi un backoff esponenziale (1 s, 2 s, 4 s, 8 s, 16 s) e si fermi dopo circa 5 tentativi. La richiesta non va persa — la coda di Certivant riprende l'elaborazione quando la dipendenza a monte si ripristina.
Un gestore degli errori robusto
async function callCertivant<T>(
fn: () => Promise<Response>,
options: { maxRetries?: number } = {},
): Promise<T> {
const maxRetries = options.maxRetries ?? 3;
let attempt = 0;
let delay = 500;
while (true) {
const res = await fn();
if (res.ok) return (await res.json()) as T;
const body = (await res.json().catch(() => null)) as
| { error?: { code: string; message: string } }
| null;
const code = body?.error?.code ?? "INTERNAL_ERROR";
// Retry on transient errors
if (
attempt < maxRetries &&
(res.status === 429 || res.status >= 500)
) {
const retryAfter =
res.status === 429
? Number(res.headers.get("X-RateLimit-Reset") ?? 60) * 1000
: delay;
await sleep(retryAfter);
delay *= 2;
attempt += 1;
continue;
}
// Bubble everything else up
throw new CertivantError(code, body?.error?.message ?? "Unknown error", res.status);
}
}
Questo schema gestisce ogni errore documentato sopra:
- Risposte di classe
200→ lette e restituite. 429→ attendeX-RateLimit-Reset, poi riprova.5xx→ backoff esponenziale, nuovo tentativo.4xx→ si interrompe subito (il Suo codice è sbagliato; nessun nuovo tentativo lo risolverà).
Riferimento API (OpenAPI)
L'intera API REST di Certivant come documento OpenAPI 3.1 — una specifica JSON pubblica che può importare in Postman o dare in pasto a un generatore di codice, più un riferimento interattivo con ogni endpoint, schema, ambito ed evento webhook.
Limiti di frequenza
Certivant applica un limite di richieste API al minuto basato sul piano — impari a leggere le intestazioni dei limiti di frequenza, a gestire le risposte 429, a riprovare correttamente e a progettare la Sua integrazione per restare entro il limite.