RiferimentoErrori

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."
    }
  }
}
CampoTipoNote
successbooleanoSempre false in caso di errore
error.codestringaLeggibile dalla macchina. Usi questo valore per la logica di controllo
error.messagestringaLeggibile da una persona. Sicuro da registrare; non sicuro da mostrare direttamente ai richiedenti
error.fieldsoggettoPresente 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

HTTPerror.code tipicoSignificato
400VALIDATION_ERRORIl corpo della richiesta non ha superato la validazione Zod. Controlli fields
400BAD_REQUESTRichiesta non valida generica (per esempio inviare prima che siano caricati tutti i documenti)
401UNAUTHORIZEDChiave API mancante, malformata, revocata o scaduta
402verification_unavailableL'organizzazione non ha più credito e non è impostata per continuare senza credito
403FORBIDDENLa 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
404NOT_FOUNDLa risorsa (req_…, doc_…, ecc.) non esiste o non è visibile all'organizzazione di questa chiave
409CONFLICTTransizione di stato non consentita (per esempio inviare una richiesta due volte), oppure violazione di un vincolo di unicità (externalRef già in uso)
413BAD_REQUESTCaricamento di un file superiore a 10 MB
415BAD_REQUESTContent-Type non supportato per l'endpoint (per esempio un corpo JSON inviato a un endpoint multipart)
429RATE_LIMITEDSuperato il limite di frequenza al minuto. Vedi Limiti di frequenza
500INTERNAL_ERRORErrore imprevisto del server. Sempre registrato dalla nostra parte; riprovare è sicuro
502BAD_GATEWAYUn servizio a monte (fornitore di sanzioni, gateway di pagamento, registro) non è disponibile. Riprovi dopo una pausa
503SERVICE_UNAVAILABLEDatabase 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 → attende X-RateLimit-Reset, poi riprova.
  • 5xx → backoff esponenziale, nuovo tentativo.
  • 4xx → si interrompe subito (il Suo codice è sbagliato; nessun nuovo tentativo lo risolverà).