spicyapiDocumentazione
Sviluppare con l’API
Contenuto principale

Preventivi e compatibilità di protocollo

Scopri il prezzo esatto di una richiesta prima di pagare, inviala a quel prezzo, rimedia a una risposta andata persa e capisci come vengono prezzate le API compatibili per testo e video.

Chiedere il preventivo di una richiesta esatta

Un preventivo ti dice quanto costa una richiesta precisa prima che tu paghi. È gratuito, non crea alcuna attività e non accantona denaro. Poi invii la stessa identica richiesta con il preventivo allegato, e così viene accettata solo al prezzo che ti è stato mostrato.

I comandi qui sotto sono per un terminale macOS o Linux, con SPICY_API_KEY impostata come spiegato nell’Avvio rapido. MODEL_ID_FROM_CATALOG è un segnaposto: al suo posto metti un valore model preso dal tuo catalogo in tempo reale (GET /api/v1/models), e prendi ogni campo di input dallo schema di quel modello.

Salva la richiesta che intendi inviare

Crea un file chiamato request.json che contenga esattamente il model, l’input e l’eventuale callBackUrl che invierai:

request.json
{
  "model": "MODEL_ID_FROM_CATALOG",
  "input": { "prompt": "A cinematic night portrait" }
}

Chiedi il prezzo

curl https://api.spicyapi.ai/api/v1/jobs/quote \
  -H "Authorization: Bearer $SPICY_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @request.json
{
  "code": 200,
  "msg": "success",
  "data": {
    "quoteId": "QUOTE_ID_FROM_RESPONSE",
    "model": "MODEL_ID_FROM_CATALOG",
    "estimatedCost": "0.008",
    "maxCharge": "0.008",
    "currency": "USD",
    "quantity": "1",
    "unit": "per_image",
    "expiresAt": "2026-09-17T10:05:00Z"
  },
  "request_id": "req_01k3m8x9q2z4v7n5p6r8s0t1w2"
}

Gli importi sono stringhe decimali in dollari statunitensi. maxCharge è il massimo che questa richiesta può costare; oggi coincide sempre con estimatedCost. quantity e unit indicano che cosa viene conteggiato, per esempio i secondi di video. Mostra l’importo ed expiresAt a chi deve approvare la spesa.

Un preventivo esegue gli stessi controlli di un invio reale, quindi può già fallire a questo punto: 400 (l’input non corrisponde allo schema del modello), 40201 (saldo insufficiente), 40202 (è stato raggiunto un limite di spesa della chiave o la quota della piattaforma) oppure 403 (questa chiave non può usare il modello).

Invia la stessa richiesta con il preventivo allegato

Entro cinque minuti, invia a createTask la richiesta senza modifiche, con due campi in più: quoteId, preso dal preventivo, ed expectedCost, uguale all’estimatedCost del preventivo. Questo passaggio costa denaro.

submit.json
{
  "model": "MODEL_ID_FROM_CATALOG",
  "input": { "prompt": "A cinematic night portrait" },
  "quoteId": "QUOTE_ID_FROM_RESPONSE",
  "expectedCost": "0.008"
}
SPICY_IDEMPOTENCY_KEY="$(uuidgen)"   # una volta per ogni nuova attività; riusala solo per reinviare questa stessa richiesta

curl https://api.spicyapi.ai/api/v1/jobs/createTask \
  -H "Authorization: Bearer $SPICY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $SPICY_IDEMPOTENCY_KEY" \
  --data-binary @submit.json

La risposta è la normale risposta 202 Accepted di un’attività, descritta nell’Avvio rapido. Il preventivo non sostituisce l’Idempotency-Key: invia entrambi.

Il preventivo è legato aSmette di valere quando
Il tuo account e la chiave API che l’ha richiestoInvii la richiesta con un’altra chiave
Il model, l’input e il callBackUrl esattiUno di questi cambia, anche solo di un carattere nel prompt. L’ordine dei campi e gli spazi non contano
Il prezzo in quel momentoPassano cinque minuti, oppure il prezzo cambia

40901 significa che il preventivo non descrive più la richiesta

Input modificati, un’altra chiave API, un preventivo scaduto, un prezzo cambiato o un expectedCost diverso da quello del preventivo si manifestano tutti allo stesso modo: l’accettazione fallisce con 40901 e non viene addebitato nulla. Chiedi un nuovo preventivo e conferma di nuovo: non togliere quoteId ed expectedCost per far passare la richiesta senza un prezzo confermato.

Anche POST /api/v1/jobs/stream, lo stream di testo nativo, accetta un preventivo allo stesso modo; vedi Testo e streaming.

Rimediare a una risposta andata persa

Se un invio è andato in timeout o la connessione è caduta, non sai se la richiesta è stata accettata. Per createTask, retry e POST /v1/videos:

  1. Reinvia la richiesta originale con la sua Idempotency-Key originale, usando la stessa chiave API. Ti torna l’attività originale, nel suo stato attuale, e non paghi due volte.
  2. Non creare un’altra attività con una chiave nuova. Una chiave nuova significa una nuova generazione e un nuovo addebito.
  3. Il reinvio di una richiesta già accettata resta valido anche dopo la scadenza del preventivo. La scadenza controlla l’accettazione, non l’attività che l’accettazione ha già creato.
  4. Un 409 non significa «non creata». O la richiesta è cambiata (è un lavoro nuovo, che richiede una chiave nuova), oppure è stata inviata con un’altra chiave API dello stesso account (reinviala con la chiave originale). Vedi Idempotenza.
  5. Per l’addebito definitivo, leggi cost e settled da recordInfo.

Le richieste di testo e in streaming non si recuperano così

La risposta a una richiesta di testo (/api/v1/jobs/stream e gli endpoint di testo sotto /v1 e /v1beta) ti viene inviata man mano che viene generata e non viene archiviata. Reinviare una chiave già accettata restituisce un errore invece della risposta: 400 se il corpo è lo stesso, 409 se è diverso. Non viene addebitato altro, ma la risposta persa non si può recuperare. Per ottenere di nuovo una risposta, invia la richiesta con una chiave nuova e pagala. Vedi Idempotenza.

Una stima non è una liquidazione

estimatedCost è quanto prevediamo di addebitare. Un marcatore di fine testo in uno stream dice soltanto che i byte hanno smesso di arrivare. Nessuno dei due dimostra che l’addebito sia definitivo. Per le attività lo dimostra settled: true insieme a cost in recordInfo. Le chiamate di testo non restituiscono un ID attività: trovi il loro addebito elencando le attività con la stessa chiave API (GET /api/v1/jobs) oppure in Console → Log, e consideri cost definitivo quando settled è true.

I preventivi negli strumenti ufficiali

La CLI e il server MCP chiedono un preventivo e interpellano una persona prima di ogni chiamata a pagamento, quindi non devi costruire tu questo passaggio:

  • CLI: spicyapi tasks quote calcola il prezzo di una richiesta; spicyapi tasks create chiede di nuovo il preventivo, mostra l’importo e chiede conferma prima di creare l’attività. Vedi Costi, conferme e sicurezza.
  • MCP: l’assistente può chiedere preventivi liberamente, ma per creare un’attività ti chiede conferma tramite il tuo client IA, mostrandoti il prezzo. Vedi Costi, conferme e sicurezza.
  • SDK: quoteTask restituisce il preventivo; passa il suo quoteId e il suo estimatedCost a createTask o a run.

Un agente non deve confermare al posto dell’utente

La conferma esiste perché sia una persona a decidere. Un agente che risponde da solo, o un client impostato per approvare automaticamente, ha eliminato l’unico argine alla spesa su quel percorso.

Compatibilità per testo e video

SpicyAPI parla anche i formati OpenAI, Anthropic e Google Gemini per i modelli di testo, e il formato OpenAI Videos per i video. L’elenco completo degli endpoint è in OpenAPI ed elenco degli endpoint; richieste, stream ed errori protocollo per protocollo sono in Testo e streaming.

URL di base. Il formato OpenAI usa https://api.spicyapi.ai/v1. Gli SDK Anthropic e Google GenAI aggiungono da soli /v1 o /v1beta, quindi imposta il loro URL di base su https://api.spicyapi.ai.

Credenziale. Una sola chiave API per tutti, nell’intestazione Authorization: Bearer. Sono accettate anche l’intestazione x-api-key usata dall’SDK Anthropic e l’intestazione x-goog-api-key usata dall’SDK Google GenAI. Un ?key= nell’URL, invece, non viene mai accettato.

Modello. Scegli un modello esatto dal catalogo in tempo reale. Il funzionamento di strumenti, messaggi con immagini e opzioni di generazione dipende dallo schema di quel modello, non dal protocollo che hai scelto.

Forma della risposta. Ogni protocollo restituisce la propria struttura di risposta, non quella della piattaforma {code, msg, data, request_id}.

Campi di ragionamento

I modelli di chat che espongono il testo del ragionamento possono restituire una stringa facoltativa in message.reasoning_content, oppure in delta.reasoning_content durante lo streaming. Quando prosegui dopo una chiamata a uno strumento, puoi conservarla nel messaggio dell’assistente corrispondente, se lo schema del modello in tempo reale lo supporta.

usage.completion_tokens_details.reasoning_tokens descrive la parte di ragionamento già inclusa in completion_tokens: non sommarla una seconda volta. Non tutti i modelli restituiscono il testo del ragionamento o questi dettagli sui token.

Due particolarità da conoscere prima di iniziare

  • Responses richiede l’intera conversazione in input. previous_response_id non è supportato.
  • Videos accetta un JSON con model, prompt, input_reference, seconds e size, che vengono mappati sui campi propri del modello. L’id del video restituito è anche un ID attività accettato da recordInfo. Il suo endpoint dei contenuti reindirizza con HTTP 302 a un URL firmato di breve durata.

Le API compatibili fissano il prezzo al momento dell’accettazione

quoteId ed expectedCost valgono solo per jobs/createTask e jobs/stream. /v1 e /v1beta applicano il prezzo in vigore quando la richiesta viene accettata e rifiutano questi due campi, quindi su quel percorso non c’è una conferma del prezzo per singola chiamata. Quando un flusso di lavoro deve confermare un tetto all’addebito, usa l’API nativa delle attività; per limitare tutto ciò che una chiave può spendere, imposta i suoi limiti giornaliero, mensile e complessivo come spiegato in Autenticazione.

Per un esempio di chat in streaming con i client ufficiali OpenAI, Anthropic e Google, vedi Usare un SDK ufficiale. La CLI e il server MCP inviano e seguono attività native; non trasmettono in streaming i token della chat.

In questa pagina