code leggibile dalla
macchina, non il message umano (i messaggi possono cambiare; i codici sono stabili).
L’envelope di errore
Le risposte andate a buon fine non contengono mai un oggetto
error. Ramifica prima
sullo stato HTTP, poi su error.code.Codici di errore
invalid_api_key
HTTP 401. L’header Authorization è mancante o malformato, oppure la chiave è
sconosciuta, scaduta o revocata — oppure il creatore della chiave non è più membro
dell’organizzazione. Le chiavi scadute e quelle sconosciute sono intenzionalmente
indistinguibili.
Authorization: Bearer samsa_sk_…. Se la chiave
è stata revocata o è scaduta, creane una nuova.
Non riprovare — il risultato non cambierà.
missing_scope
HTTP 403. La chiave è valida ma le manca lo scope
richiesto dall’endpoint. param è "scope" e il messaggio nomina lo scope mancante.
insufficient_credits
HTTP 402. Il pool di credits spendibili dell’organizzazione (abbonamento più
top-up validi) è al di sotto del costo dell’azione. Consulta Prezzi.
Se l’organizzazione ha almeno un team attivo, l’API restituisce invece i codici
legati ai team insufficient_team_credits o
insufficient_unallocated_credits — con
due eccezioni. Un’organizzazione di sistema esente dal budgeting per team resta nel
regime org e mantiene questo codice generico anche con team attivi. E un guasto
operativo nella detrazione stessa (per esempio una lettura del saldo degradata) ricade
su questo codice generico qualunque sia il regime di budget. Un semplice
insufficient_credits in una configurazione con team può quindi essere transitorio;
riprova prima di trattarlo come un saldo esaurito.
GET /credits
mostra un available che copre il costo, potresti aver incontrato il fallback
operativo — riprova una volta. Quella lettura è però un’istantanea: anche un
cambiamento di stato dopo il rifiuto (un top-up, un rimborso, un budget modificato o
un reset del periodo) può spiegarlo, quindi una reale carenza non è esclusa.
Altrimenti ricarica o esegui l’upgrade del piano dell’organizzazione nell’app, poi
riprova. Nulla è stato addebitato e nessun job è stato creato.
subscription_inactive
HTTP 402. L’organizzazione non ha alcun abbonamento utilizzabile (nessuno attivo,
in periodo di grazia o con top-up spendibili). Distinto da insufficient_credits,
dove un abbonamento esiste ma il pool è troppo basso.
insufficient_team_credits
HTTP 402. Le organizzazioni possono suddividere i loro credits mensili
dell’abbonamento in budget per team, e ogni chiave API può essere assegnata a un
team. Una chiave assegnata a un team con budget spende dal bucket mensile di quel
team; tutto ciò che non è allocato ad alcun budget di team forma il pool non
allocato dell’organizzazione. I top-up acquistati sono esenti dai budget e restano
disponibili per coprire il resto. Questo codice si verifica quando il saldo che la chiave può
spendere — il minore tra il pool del piano residuo dell’organizzazione e il budget residuo
del team, più i top-up — è al di sotto del costo dell’azione. È esattamente l’available
riportato da GET /credits.
Il codice indica il regime di budget, non il saldo che si è esaurito. Una chiave
assegnata a un team con budget riceve questo codice anche quando a esaurirsi è stato il
pool del piano dell’organizzazione e non il budget del team — il team può quindi mostrare
ancora margine. Confronta
plan_credits con scope.remaining su
GET /credits per vedere quale dei due vincola.insufficient_unallocated_credits
HTTP 402. La chiave non è assegnata a un team con budget (non assegnata, o il
suo team non ha budget), quindi spende dal pool non allocato dell’organizzazione — i
credits mensili dell’abbonamento rimanenti dopo aver sottratto i budget di tutti i
team attivi. Questo codice si verifica quando il saldo che la chiave può spendere — il minore
tra il pool del piano residuo dell’organizzazione e il margine di quel pool non allocato, più
i top-up esenti dai budget — è al di sotto del costo dell’azione, con la stessa avvertenza
vista sopra su quale saldo si sia davvero esaurito. Le organizzazioni senza alcun team attivo
non vedono mai i due codici legati ai team — ricevono invece il semplice
insufficient_credits.
not_found
HTTP 404. L’id è sconosciuto, oppure appartiene a un’altra organizzazione. I due
casi sono indistinguibili per progettazione, così l’esistenza non viene mai rivelata
tra organizzazioni.
validation_error
HTTP 422. Il corpo della richiesta o un parametro non ha superato la validazione.
param nomina il campo problematico; message spiega il vincolo.
message e param, poi
reinviala. Questo è un errore del client — riprovare la stessa richiesta fallirà in
modo identico.
svg_acceptance_required
HTTP 422. Solo POST /images/vectorizations
restituisce questo codice. L’SVG è un’esclusione di ambito documentata ai sensi
dell’art. 50(2) del regolamento europeo sull’IA: un SVG non può portare un manifesto C2PA
né una filigrana incorporata, quindi gli output vettoriali sono consegnati non
firmati. svg_acceptance deve perciò essere il booleano letterale true — un valore
mancante, false o altro viene rifiutato con questo codice dedicato, mai con il
validation_error generico. L’accettazione è divulgazione / prova di
audit, non una rinuncia alla conformità. Non viene addebitato nulla e non viene creato
alcun job.
"svg_acceptance": true non appena la tua
integrazione mostra l’avviso di output non firmato a chi opera sul risultato.
svg_phase1_scope_out_required
HTTP 403. Anche questo riguarda solo la vettorizzazione ed è diverso da
missing_scope — lo scope della chiave va bene. La consegna richiede
inoltre un’accettazione dei ToS/AUP attuale e verificata lato server; il flag
svg_acceptance della richiesta non è mai considerato quella prova. All’invio,
un’accettazione mancante o scaduta viene rifiutata prima di qualsiasi addebito. Il
controllo viene rieseguito alla consegna: un job già accettato può quindi essere ancora
rifiutato da
GET /images/vectorizations/{id} o
all’invio del webhook se nel frattempo l’accettazione scade — un rifiuto in consegna non
aggiunge addebiti, ma non rimborsa i crediti già consumati dal job completato.
GET — il webhook non viene
reinviato automaticamente. Accettare è divulgazione, non una rinuncia.
rate_limited
HTTP 429. La chiave ha superato la sua finestra di rate di richieste per chiave.
La risposta contiene gli header Retry-After e X-RateLimit-*. Consulta
Rate limits.
Retry-After. Usa un
backoff esponenziale per 429 ripetuti.
too_many_active_jobs
HTTP 429. L’organizzazione ha raggiunto il suo tetto di job concorrenti in corso.
Il messaggio include il conteggio attuale e il limite, ed è impostato un header
Retry-After.
GET o usa un webhook) prima di
inviarne altri, poi riprova dopo Retry-After.
upload_in_progress
HTTP 409. Solo upload di immagini: un’altra
chiamata POST /images/uploads/{id}/complete per lo stesso upload è in corso.
idempotency_key_reused
HTTP 409. Solo con il miglioramento dei prompt
(in arrivo):
l’header Idempotency-Key è già stato usato nelle ultime 24 ore con un body di
richiesta diverso. Una chiave appartiene sempre a una sola richiesta. Non è stato
addebitato nulla.
Idempotency-Key per una nuova richiesta. Non
riprovare con la stessa chiave — il risultato non cambierà.
idempotency_in_progress
HTTP 409. Solo con il miglioramento dei prompt
(in arrivo):
una richiesta con lo stesso Idempotency-Key e lo stesso body è ancora in corso.
Questa richiesta non è stata addebitata.
Idempotency-Replayed: true.
too_many_pending_uploads
HTTP 429. Solo upload di immagini: hai 20
upload preparati ma non completati. Il messaggio include il conteggio attuale e il
limite, ed è impostato un header Retry-After.
Retry-After), poi prepara di nuovo.
internal_error
HTTP 500. Un errore inaspettato dalla parte di Samsa. La risposta non rivela mai
dettagli interni — il request_id è il tuo riferimento per il supporto.
request_id.
refund_pending
HTTP 500. Solo con il miglioramento dei prompt
(in arrivo):
il provider di IA è fallito dopo l’addebito del credit e il rimborso non ha potuto
essere confermato subito. Il rimborso è registrato e Samsa lo ripete automaticamente
finché non va a buon fine.
Idempotency-Key (la vecchia chiave restituisce questo errore). Se il
credit non è tornato dopo un’ora, contatta support@samsa.ai
con il request_id.
provider_error
HTTP 502. Solo con il miglioramento dei prompt
(in arrivo):
il provider di IA è fallito o non ha restituito un risultato utilizzabile. Il credit
addebitato per la chiamata è stato rimborsato prima di questa risposta.
Idempotency-Key — la vecchia
chiave restituisce questo errore. Alla fine non è stato addebitato nulla.
service_unavailable
HTTP 503. Una funzione è disattivata o temporaneamente non disponibile. Oggi è il
caso del miglioramento dei prompt, che non è
ancora attivato (Prompt improvement is not available yet.), e può riguardare anche
altre funzioni, come la creazione di modelli.
Con il miglioramento dei prompt (in arrivo), un 503 significa anche che Samsa non ha
potuto confermare lo stato di idempotenza o l’esito dell’addebito della richiesta:
nessun prompt è stato consegnato, e un credit addebitato viene rimborsato
automaticamente.
Idempotency-Key non
viene mai addebitato due volte.
Usare request_id per il supporto
Ogni errore (e ogni successo) porta un request_id, restituito anche come header di
risposta X-Request-ID. Collega il tuo errore lato client, l’header di risposta e i
log del server di Samsa a una singola richiesta. Registralo e citalo quando contatti
support@samsa.ai — è il modo più rapido per noi di trovare
esattamente cosa è successo.