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.
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.
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.

