Catalogo dei modelli e schemi
Usa il catalogo autenticato aggiornato per scegliere modelli utilizzabili, leggere i prezzi e creare richieste dal JSON Schema corrente.
createTask.model richiede il valore esatto di model restituito dalla risposta autenticata di GET /api/v1/models. Il suo input è definito dall'inputSchema corrente della stessa voce. Quella risposta ottenuta durante l'esecuzione è l'unica fonte di verità per un ID utilizzabile.
Non copiare un ID da una pagina statica
Snapshot al lancio, pagine delle famiglie e cataloghi dei creatori dei modelli servono a scoprire i prodotti. Possono includere voci pianificate, disabilitate o rinominate e non devono mai essere usati come ripiego quando il catalogo aggiornato è vuoto. Prima di eseguire attività a pagamento, recupera il catalogo autenticato e richiedi sia enabled: true sia available: true.
Negli esempi di questa pagina, MODEL_ID_FROM_CATALOG è un segnaposto, non un modello reale: sostituiscilo con un valore di model del tuo catalogo aggiornato. Leggere il catalogo è gratuito.
Selezionare un modello e il suo input validato
Gli schemi delle richieste variano fra modelli, quindi il percorso sicuro ed eseguibile seleziona insieme un modello attualmente disponibile e uno dei suoi esempi validati dal server:
const response = await fetch(
'https://api.spicyapi.ai/api/v1/models?includeSchema=1&includeExamples=1',
{ headers: { Authorization: `Bearer ${process.env.SPICY_API_KEY}` } },
);
const envelope = await response.json();
if (!response.ok || envelope.code !== 200) throw new Error(envelope.msg);
const selected = envelope.data.items.find(
(item) => item.enabled && item.available && item.examples?.length,
);
if (!selected) throw new Error('No callable model with a validated example');
const createTaskBody = {
model: selected.model,
input: selected.examples[0].input,
};Ogni esempio è un input completo che il server ha già validato rispetto allo schema corrente, quindi può essere inviato così com'è.
Leggere il catalogo da codice
GET /api/v1/models
GET /api/v1/models/{model}curl "https://api.spicyapi.ai/api/v1/models?modality=video" \
-H "Authorization: Bearer $SPICY_API_KEY"L'elenco non è paginato: una risposta contiene ogni modello visibile alla tua chiave che corrisponde ai filtri. Tutti i parametri sono facoltativi.
| Parametro | Significato |
|---|---|
modality | image, video, audio oppure text |
provider | Il creatore del modello, con corrispondenza esatta e distinzione fra maiuscole e minuscole, per esempio ByteDance. Copialo dal provider di una voce |
task | Una singola attività, per esempio text-to-image, edit (modifica di immagini), image-to-video, text-to-video, reference-to-video, speech-to-text, video-analyze, video-edit, video-extend, character-animation oppure chat. Leggi tasks nel catalogo per l'insieme attuale. La modifica di immagini accetta due forme: i modelli vengono pubblicati come .../edit, ma tasks li classifica come image-to-image e il filtro accetta entrambe |
search | Testo cercato senza distinzione fra maiuscole e minuscole in qualsiasi parte dell'ID del modello o del nome visualizzato, fino a 128 caratteri |
includeSchema | true oppure 1 aggiunge l'inputSchema di ogni voce |
includeExamples | true oppure 1 aggiunge gli examples di ogni voce, validati rispetto allo schema corrente |
L'endpoint del singolo modello, GET /api/v1/models/{model}, include sempre inputSchema ed examples; includeSchema e includeExamples hanno effetto soltanto sull'elenco. Le barre nell'ID possono rimanere come sono; codificale con percent-encoding soltanto se il client HTTP tratta un parametro di percorso come un unico segmento. Un modello che non esiste o non è attualmente offerto restituisce 404.
Una risposta abbreviata dell'elenco:
{
"code": 200,
"msg": "success",
"data": {
"total": 1,
"items": [
{
"model": "MODEL_ID_FROM_CATALOG",
"family": "…",
"displayName": "…",
"provider": "…",
"modality": "video",
"tasks": ["image-to-video"],
"async": true,
"enabled": true,
"available": true,
"availability": "available",
"taskTimeoutSeconds": 1200,
"maxOutputDurationSeconds": 10,
"quantityField": "duration_seconds",
"pricing": [
{ "variant": "generate_audio=false;resolution=720p", "unit": "per_second", "price": "0.05", "currency": "USD" },
{ "variant": "generate_audio=true;resolution=720p", "unit": "per_second", "price": "0.08", "currency": "USD" }
],
"startingPrice": { "variant": "generate_audio=false;resolution=720p", "unit": "per_second", "price": "0.05", "currency": "USD" },
"badges": ["audio_output"],
"relatedModels": [],
"version": "v1",
"updatedAt": "2026-09-16T16:47:57Z"
}
]
},
"request_id": "req_01k3m8x9q2z4v7n5p6r8s0t1w2"
}I prezzi sopra sono illustrativi. inputSchema ed examples compaiono nelle voci dell'elenco soltanto quando li richiedi.
Campi da usare nei client
| Campo | Scopo |
|---|---|
model | Il valore esatto da inviare come createTask.model, nella forma publisher/model/task |
family | Identificativo stabile della famiglia di prodotto per raggruppare endpoint correlati |
displayName | Nome leggibile di questo endpoint |
provider | Il creatore del modello, per esempio il laboratorio che l'ha sviluppato |
modality / tasks | Il tipo di media sotto cui l'endpoint è raggruppato nel catalogo e l'attività che esegue. modality guida la navigazione e il filtro modality; non promette il tipo di artefatto: un endpoint speech-to-text è raggruppato sotto audio e risponde con testo. Consulta Struttura dell'output |
toolkit | La famiglia di strumenti a cui appartiene questo endpoint, attualmente soltanto subject-swap. È assente quando il modello non fa parte di un toolkit, quindi controlla il valore invece della chiave. Come badges, è una classificazione e non influisce mai sull'accettazione, sul prezzo o sulla validazione. Consulta Sostituzione del soggetto |
async | true: crea un'attività e raccogli il risultato con polling o webhook. false: la risposta arriva direttamente nella risposta alla chiamata |
inputSchema | JSON Schema 2020-12 usato per generare moduli e validare le richieste |
examples | Input validati rispetto allo schema corrente; nell'elenco vengono restituiti soltanto su richiesta |
enabled | Indica se la voce può essere chiamata adesso. Il catalogo elenca anche voci pubblicate ma non ancora aperte e voci sospese dalla piattaforma: queste restituiscono false. Controllalo insieme ad available prima di inviare un'attività |
available | Indica se il modello può essere chiamato adesso. false significa che una chiamata fallirebbe, per esempio perché manca un prezzo attuale |
availability | La fase dichiarata: planned, available, preview (campi e output potrebbero ancora cambiare) oppure maintenance (temporaneamente non funzionante, con ritorno previsto) |
pricing / startingPrice | I tuoi prezzi; consulta Leggere i prezzi |
quantityField | Il campo di input il cui valore è la quantità fatturata, spesso duration_seconds per i video. Vuoto significa che ogni chiamata conta come un'unità. Leggilo sempre dal catalogo |
taskTimeoutSeconds | La scadenza di esecuzione della piattaforma per una singola attività. Non è la durata del media |
maxOutputDurationSeconds | La durata massima dell'output producibile dal modello, tratta dal maximum della sua proprietà duration_seconds; omesso se non viene dichiarato un massimo |
badges | Etichette di capacità e licenza, per esempio commercial_use o no_watermark. Ignora i valori che non riconosci |
relatedModels | Alternative o passaggi successivi selezionati, come ID di modelli che puoi chiamare |
version / updatedAt | Tracciamento delle modifiche: confrontali per capire se una lettura successiva abbia cambiato qualcosa |
mature e policyTier sono etichette informative. Non influiscono sull'accettazione di una richiesta.
Leggere i prezzi
Ogni voce in pricing è una fascia di prezzo:
| Campo | Significato |
|---|---|
unit | per_image, per_second (di media in output), per_request oppure per_1k_tokens |
price | Il tuo prezzo per unità in dollari statunitensi, come stringa decimale. Riflette già le tariffe del tuo account, che possono differire fra account |
variant | Le impostazioni che selezionano questa fascia. Vuoto quando il modello ha un unico prezzo; il valore semplice (per esempio 720p) quando un solo campo seleziona la fascia; coppie field=value unite da ; e ordinate per nome di campo (per esempio generate_audio=false;resolution=480p) quando sono coinvolti più campi |
currency | Sempre USD |
regularPrice, offerLabel, offerPercent, offerEndsAt | Presenti soltanto quando si applica un'offerta al cliente: prezzo precedente all'offerta, nome dell'offerta, percentuale e scadenza |
startingPrice è la voce più economica, non il prezzo delle tue impostazioni. I campi che selezionano una fascia sono elencati in inputSchema["x-pricing"].variantFields, quando presente, altrimenti sono quelli contrassegnati con x-ui.affects_price: true (escluso quantityField). Un campo omesso viene conteggiato con il suo default nello schema.
- Modelli multimediali: il costo è
price × quantity, dove la quantità è il valore diquantityFieldnell'input (oppure un'unità quandoquantityFieldè vuoto). Alcuni endpoint aggiungono poi un addebito separato per ogni input extra, più spesso uno per immagine di riferimento. Consideralo una parte effettiva del conto, non un dettaglio di arrotondamento: su un endpoint di modifica che accetta un array di immagini di riferimento, riempire l'array può moltiplicare l'importo, mentreunit,quantity,variante ilpricedella fascia restano esattamente quelli di una sola immagine; il calcolo sopra sottostima quindi il costo senza alcun segnale visibile. Il segnale leggibile dalle macchine è un campo contrassegnato conx-ui.affects_price: trueche non è néquantityFieldné elencato inx-pricing.variantFields: cambia l'importo senza selezionare una fascia. Per qualsiasi endpoint di questo tipo, leggipricingcome un minimo e ricava l'importo da un preventivo. - Modelli di testo (
per_1k_tokens): un solo numero non può descrivere l'addebito.priceè soltanto la tariffa dei token di output per 1.000 token. I token di input e di input in cache hanno tariffe proprie, di solito inferiori, e vengono addebitati in base all'utilizzo misurato di ogni chiamata. Non moltiplicarepriceper il conteggio totale dei token. I prezzi per milione di token di input, input in cache e output compaiono sulla pagina di ogni modello e inprice.perMillionTokensdel catalogo pubblico.
Per conoscere prima di pagare l'importo di una richiesta esatta sull'API nativa, usa POST /api/v1/jobs/quote. Gli addebiti finali sono nella registrazione dell'attività (cost con settled: true) e in Fatturazione.
Memorizzare il catalogo in cache
- La risposta del catalogo può essere memorizzata in cache per un massimo di 60 secondi (
Cache-Control: private, max-age=60). Conservala soltanto in una cache privata per account: i prezzi sono specifici dell'account, quindi non metterla mai dietro una cache CDN condivisa o pubblica. - Oltre a questo, non rileggerlo prima di ogni attività. Le letture del catalogo usano la disponibilità di lettura dell'account, indipendentemente dall'invio delle attività. Recuperarlo prima di ogni chiamata spreca comunque capacità di lettura; consulta Limiti di frequenza.
- Aggiornalo con un timer (per esempio ogni pochi minuti), dopo un errore di validazione
400e quando un invio per quel modello viene rifiutato. - Conserva
versioneupdatedAtdella registrazione usata, così puoi capire se una lettura successiva abbia cambiato qualcosa. - Non distribuire mai uno snapshot dello schema scritto nel codice e non ripiegare mai su una pagina statica quando il catalogo aggiornato non contiene una voce utilizzabile.
Regole condivise di Schema e Playground
inputSchema usa JSON Schema 2020-12. Le parole chiave standard controllano la validazione sul server; l'oggetto x-ui a livello di proprietà descrive soltanto ordine, presentazione e indicazioni per aggiornare i preventivi nel Playground. I client devono ignorare estensioni di presentazione sconosciute, che non sostituiscono mai required, enumerazioni, limiti o rami condizionali. Consulta il contratto completo di Spicy Schema.
Generare la tua tabella dei parametri per modello
Questo sito non include una tabella dei parametri per ciascun modello. Non è per pigrizia: modelli e campi cambiano ogni settimana, ogni copia statica perde aderenza e leggere un parametro obsoleto costa un errore 400 o un prezzo sbagliato. I parametri hanno esattamente una fonte: l'inputSchema restituito dal catalogo. Il Playground mostra lo stesso documento e l'SDK valida rispetto a esso.
Come tradurre ogni parte dello schema in una tabella
| Nello schema | Nella tua tabella dei parametri |
|---|---|
una chiave di properties | il nome del parametro. I nomi dei campi sono uniformati fra modelli: un significato, un nome ovunque |
presenza in required | obbligatorio oppure facoltativo |
anyOf / allOf | obbligatorio a certe condizioni. anyOf = fornisci almeno uno di questi; allOf con if → then = se fornisci A devi fornire B |
type | il tipo |
description | il testo di aiuto. È prosa inglese e può essere mostrato integralmente; non devi scriverne uno tuo |
enum | i valori accettati. Quando è presente x-ui.enum_labels, usalo per trasformare i valori in etichette leggibili |
minimum / maximum | l'intervallo accettato; x-ui.step è il passo e x-ui.unit il suffisso (s, px) |
minItems / maxItems | per un array, il numero di elementi accettati. Una riga che omette questa informazione non comunica al lettore il limite che incontrerà |
items | per un array, la struttura di un elemento. Quando items.type è object, quel sottoschema è a sua volta uno schema di oggetto completo: leggi i suoi required, additionalProperties e i valori di type, description, intervallo e default di ogni sottocampo, poi mostrali come tabella annidata invece di un campo di testo libero |
default | il valore predefinito applicato quando ometti il campo |
x-ui.order | la chiave di ordinamento, prima i valori più alti. Non ordinare secondo l'ordine delle chiavi di properties: l'ordine delle chiavi di un oggetto JSON non fa parte del contratto |
x-ui.primary | fissa in alto come input principale |
x-ui.advanced | può essere raggruppato in una sezione avanzata comprimibile |
x-ui.affects_price | contrassegnalo come influente sul prezzo; un cambiamento del valore richiede un nuovo preventivo |
x-ui.widget | quale controllo mostrare quando crei un modulo modificabile (tredici valori, consulta Spicy Schema) |
I rami condizionali compaiono soltanto alla radice di inputSchema, in due forme: anyOf, dove ogni ramo elenca soltanto i campi required («fornisci almeno uno di questi»), e allOf, dove ogni ramo è if → then («se fornisci A devi fornire B»). Non dedurli dalla famiglia e non aspettarti oneOf, not o dependentSchemas. I nuovi endpoint seguono i campi canonici di Spicy Schema; quelli precedenti seguono il proprio schema aggiornato.
Recuperarlo
const modelId = 'MODEL_ID_FROM_CATALOG'; // the exact `model` value from GET /api/v1/models
const res = await fetch(`https://api.spicyapi.ai/api/v1/models/${modelId}`, {
headers: { Authorization: `Bearer ${process.env.SPICY_API_KEY}` },
});
const { data } = await res.json();
const schema = data.inputSchema;
const rows = Object.entries(schema.properties)
.sort(([, a], [, b]) => (b['x-ui']?.order ?? 0) - (a['x-ui']?.order ?? 0))
.map(([name, prop]) => ({
name,
required: (schema.required ?? []).includes(name),
type: prop.type,
description: prop.description,
values: prop.enum
? prop.enum.map((v) => prop['x-ui']?.enum_labels?.[v] ?? v)
: prop.minimum !== undefined || prop.maximum !== undefined
? [`${prop.minimum ?? ''}–${prop.maximum ?? ''}${prop['x-ui']?.unit ?? ''}`]
: [],
default: prop.default,
affectsPrice: prop['x-ui']?.affects_price === true,
advanced: prop['x-ui']?.advanced === true,
}));Questo esempio si ferma intenzionalmente ai valori scalari: lascia values vuoto per un array, perché un array descrive ciò che accetta in items, minItems e maxItems invece che in enum o in un intervallo. Amplialo prima di distribuirlo: una riga che mostra un parametro array soltanto come array, senza la struttura degli elementi né il limite di lunghezza, è una riga su cui il lettore non può agire.
La registrazione del singolo modello restituisce anche examples: ciascuno è un input completo già validato sul server rispetto allo schema corrente, quindi funziona sia come esempio minimo eseguibile nella documentazione sia come corpo di richiesta che puoi inviare senza modifiche. È più sicuro che comporlo a mano, perché un esempio scritto manualmente diventa obsoleto quando lo schema cambia, mentre examples no.
Lo stesso codice copre qualsiasi modello cambiando modelId e non perde validità quando aggiungiamo nuovi modelli. Per generare una tabella dell'intero catalogo, scorri items da GET /api/v1/models?includeSchema=1 e memorizzala in cache come descritto in Memorizzare il catalogo in cache.
Testi di aiuto più lunghi di description
description è una frase, dimensionata per l'etichetta di un modulo. Quando un parametro richiede più spazio, il catalogo pubblico contiene una seconda nota per parametro:
curl "https://api.spicyapi.ai/console/v1/catalog/models/MODEL_ID_FROM_CATALOG?locale=en"La registrazione del singolo modello restituisce paramNotes, un oggetto con chiavi corrispondenti ai nomi dei parametri, scritto in una qualsiasi delle dieci lingue della documentazione attraverso locale. Contiene ciò che non entra in un'etichetta: rispetto a cosa viene davvero misurato un valore, quale impostazione rallenta sensibilmente una chiamata e quali input vengono accettati dallo schema ma portano comunque a un risultato deludente. Per un parametro che punta a un file ospitato da te, di solito è l'unico punto che spiega se lo recuperiamo, quando lo recuperiamo e cosa succede se risulta inutilizzabile.
Due confini: paramNotes è sul catalogo pubblico, che non richiede una chiave, e non su GET /api/v1/models autenticato, quindi leggilo separatamente e memorizzalo in cache accanto allo schema. Ed è prosa, mai una regola: inputSchema resta l'unico elemento che decide se una richiesta viene accettata.

