spicyapiDocumentazione
Riferimento
Contenuto principale

Contratto Spicy Schema

Struttura condivisa delle richieste, campi canonici, schema dei moduli, ciclo asincrono, errori, archiviazione dei risultati e compatibilità.

Spicy Schema è il contratto pubblico per ogni nuovo modello multimediale. Aggiungere un modello cambia il suo model, l'inputSchema e il prezzo al cliente; autenticazione, attività, risultati, errori e download restano gli stessi.

Questa è una pagina di riferimento. Alla maggior parte delle integrazioni basta Catalogo dei modelli e schemi. Continua se stai costruendo da inputSchema un modulo, un validatore o un generatore di codice e vuoi sapere esattamente su cosa puoi contare.

Soltanto il catalogo aggiornato dimostra che un modello sia utilizzabile

Questa pagina definisce la struttura del contratto; non afferma che qualche modello sia disponibile. Prima di un'attività a pagamento, leggi la risposta autenticata di GET /api/v1/models e richiedi sia enabled: true sia available: true. Le voci pianificate o disabilitate non possono essere chiamate.

Confine pubblico

Un ID pubblico di modello identifica una capacità stabile nella forma <publisher>/<model>/<task>. Il publisher è il creatore del modello: l'autore o l'organizzazione di ricerca che lo ha sviluppato. La modifica di immagini usa sempre il suffisso edit e gli identificativi pubblicati in precedenza restano accettati. Copia sempre un ID reale dal catalogo aggiornato; MODEL_ID_FROM_CATALOG in questa pagina è un segnaposto.

Risposte pubbliche, webhook, errori e download usano soltanto identificativi, codici di errore e URL propri di SpicyAPI. Non contengono mai dettagli interni di elaborazione, risposte grezze, errori grezzi o dati aziendali interni. I risultati vengono copiati nello storage di SpicyAPI prima di essere restituiti.

Struttura unificata di creazione

{
  "model": "MODEL_ID_FROM_CATALOG",
  "input": {
    "prompt": "slow camera push-in",
    "image_url": "spicy://f/fil_01k3m8x9q2z4v7n5p6r8s0t1w3",
    "duration_seconds": 8,
    "resolution": "1080p",
    "generate_audio": true
  },
  "callBackUrl": "https://your-app.example.com/hooks/spicy"
}
CampoRegola
modelValore esatto, attualmente utilizzabile, del catalogo autenticato aggiornato
inputDeve soddisfare l'inputSchema corrente della stessa voce; i campi sconosciuti vengono rifiutati
callBackUrlIndirizzo pubblico HTTPS facoltativo che riceve l'attività conclusa; usa esattamente queste maiuscole e minuscole. Consulta Webhook

L'input sopra è illustrativo: soltanto l'inputSchema del modello definisce quali di questi campi siano accettati.

Campi canonici

Lo stesso concetto usa un unico nome snake_case in tutti i nuovi endpoint. Questa tabella elenca i campi comuni, non tutti i campi; l'inputSchema del modello è sempre l'elenco completo.

ConcettoCampoTipo
Prompt positivopromptstringa
Prompt negativonegative_promptstringa
Immagine principale / finaleimage_url / last_image_urlriferimento a un'immagine (vedi sotto)
Più immagini di inputimage_urlsarray di riferimenti a immagini
Maschera di modificamask_urlriferimento a un'immagine
Video / audio principalevideo_url / audio_urlURL HTTPS pubblico oppure URI spicy:// confermato
Media di riferimentoreference_image_urls / reference_video_urls / reference_audio_urlsarray di riferimenti
Durata dell'outputduration_secondsnumero oppure intero
Risoluzione / rapportoresolution / aspect_ratioenumerazione documentata
Dimensione esatta dell'outputsize (un preset), oppure width / heightenumerazione documentata / intero
Frequenza dei fotogrammifpsintero
Audio nativogenerate_audiobooleano
Seed casualeseedintero
Pesi degli adattatoriloras, oppure high_noise_loras / low_noise_loras quando un endpoint espone separatamente le sue fasiarray di oggetti
Numero di outputnum_outputsintero positivo
Codificaoutput_formatenumerazione documentata
Conversazione chatmessagesarray
Lunghezza dell'output / campionamentomax_tokens / temperatureintero / numero

Un riferimento a un'immagine è un URL HTTPS pubblico, un URI spicy:// confermato da un caricamento oppure un piccolo URI data:image/…;base64,…. Video e audio non possono essere inviati inline. Consulta Media.

Una voce dei pesi degli adattatori identifica un insieme di pesi e quanto intensamente applicarlo. Il nome del campo è fisso, la struttura della voce no: ciò che un endpoint accetta per un file di pesi, un URL oppure una chiave di una libreria integrata, è specificato dal sottoschema items di quell'endpoint, quindi leggilo lì invece di presumere una forma. Lo stesso vale per il numero di voci consentite e per i sottocampi obbligatori.

Un campo specifico del modello esiste soltanto quando rappresenta una capacità reale non già coperta da un campo canonico e prende il nome di quella capacità. Un endpoint precedente può conservare nomi di campi precedenti nel proprio inputSchema aggiornato; i nuovi endpoint non li copiano.

inputSchema e annotazioni UI

Ogni modello usa JSON Schema 2020-12 in inputSchema. Lo stesso schema guida validazione sul server, moduli del Playground, esempi e preventivi. L'SDK TypeScript ufficiale tipizza staticamente le strutture comuni delle richieste e delle risposte; l'input di ciascun modello resta Record<string, unknown> e deve essere validato rispetto allo schema aggiornato, senza presumere di avere campi generati per ogni modello.

Questo sito non conserva una tabella di parametri per modello. I parametri hanno esattamente una fonte: l'inputSchema restituito da GET /api/v1/models?includeSchema=1, che è anche ciò che mostra il Playground. Una copia statica perde aderenza quando i modelli cambiano e niente può rilevare quella divergenza. Per costruire la tua tabella dallo schema, consulta Catalogo dei modelli e schemi.

Ogni schema che ricevi:

  • ha una radice object e rifiuta i campi sconosciuti (additionalProperties: false);
  • dichiara required, tipi, enumerazioni, intervalli, lunghezze, limiti degli array, formati URI, valori predefiniti e condizioni verificate;
  • assegna a ogni proprietà una description inglese non vuota;
  • omette campi e valori predefiniti non verificati, anziché indovinarli;
  • esprime le condizioni tramite anyOf / allOf alla radice (sotto), mai soltanto attraverso la visibilità UI;
  • non contiene interruttori che cambiano soltanto l'elaborazione interna né interruttori per filtrare i contenuti.

Annotazioni di presentazione: x-ui

I metadati di presentazione non sono un secondo schema di validazione. Sono tutti nell'oggetto x-ui della proprietà stessa, le cui chiavi sono snake_case e appartengono a un insieme chiuso:

ChiaveSignificato
widgetcontrollo da mostrare; valori sotto
order**l'**ordine dei campi, prima i valori più alti, univoco all'interno di un endpoint
label / placeholdersostituzione dell'etichetta predefinita; testo segnaposto dell'input
rowsnumero di righe dell'area di testo
step / unitpasso numerico e suffisso dell'unità (s, px)
accept / max_size_mbfiltro MIME e limite di dimensione per file dei controlli di caricamento
advancedappartiene a una sezione avanzata comprimibile
primaryinput principale; fissato in alto e mai compresso
affects_pricecambiare questo valore richiede un nuovo preventivo
visible_whenespressione di visibilità condizionale
enum_labelscorrispondenza fra valore di enumerazione ed etichetta visualizzata

x-ui.widget è uno dei tredici valori: textarea, text, upload, multi-upload, select, radio, slider, number, switch, json, object-list, chat-messages, hidden. Un widget è sempre coerente con la struttura dei dati, quindi un renderer può scegliere direttamente in base a esso: select e radio includono sempre un enum; slider include sempre sia minimum sia maximum (mai soltanto exclusiveMinimum / exclusiveMaximum); switch è sempre un boolean; multi-upload è un array con items.type: string; object-list è un array con items.type: object e items.properties, con ogni sottocampo dotato dei propri type e description; chat-messages è un array; hidden significa che il campo viene comunque inviato ma non ha un controllo.

Per qualsiasi campo array, i suoi minItems / maxItems e il sottoschema items contengono vincoli mai menzionati dall'elenco required alla radice, che il server applica esattamente come il resto dello schema. In un object-list, items è a sua volta uno schema di oggetto completo: i propri required, il proprio additionalProperties: false e il proprio tipo, intervallo e default per ogni sottocampo. I valori predefiniti si applicano anche all'interno di quelle voci: un sottocampo omesso viene compilato con il suo default prima della validazione, quindi un sottocampo obbligatorio con un valore predefinito è di fatto facoltativo. Uno senza valore predefinito viene rifiutato se manca, così come un sottocampo sconosciuto o un valore fuori dal suo intervallo.

Un 400 dovuto a un valore dentro un array indica la voce esatta, cioè campo, indice a base zero e sottocampo, anziché la richiesta nel suo complesso. Passa quell'indicazione a chi deve correggerla: con varie voci in elaborazione, sapere quale sia fuori intervallo fa la differenza fra una correzione di una riga e una ricerca per esclusione.

I client devono ignorare le chiavi di presentazione sconosciute: aggiungere una chiave x-ui è una modifica retrocompatibile.

{
  "type": "object",
  "required": ["prompt", "duration_seconds"],
  "additionalProperties": false,
  "properties": {
    "prompt": {
      "type": "string",
      "minLength": 1,
      "description": "Describes the scene and its motion.",
      "x-ui": { "widget": "textarea", "order": 100, "primary": true, "rows": 4 }
    },
    "duration_seconds": {
      "type": "integer",
      "enum": [5, 8, 10],
      "description": "Output duration in seconds.",
      "x-ui": { "widget": "radio", "order": 90, "unit": "s", "affects_price": true }
    }
  },
  "x-pricing": { "variantFields": ["duration_seconds"], "billingMode": "variant_matrix" }
}

Ogni description è prosa inglese e può essere mostrata integralmente come testo di aiuto del campo.

x-ui.affects_price: true indica alla UI di aggiornare un preventivo dopo la modifica del campo. Non è una formula di prezzo e non sostituisce mai il pricing del catalogo o quantityField. Il x-pricing alla radice è la rappresentazione sul server dello stesso fatto: variantFields elenca i campi che selezionano una fascia di prezzo ed è sempre un sottoinsieme dei campi affects_price: true, mentre billingMode dice come viene misurato l'utilizzo dell'endpoint. Entrambi sono indicazioni; l'importo autorevole è quello restituito da catalogo, preventivo e attività. Il modo in cui le fasce compaiono in pricing è descritto in Leggere i prezzi.

Campi condizionali

Le condizioni assumono esattamente due forme, entrambe alla radice:

{
  "anyOf": [{ "required": ["image_url"] }, { "required": ["image_urls"] }],
  "allOf": [
    { "if": { "required": ["last_image_url"] }, "then": { "required": ["image_url"] } },
    { "if": { "properties": { "resolution": { "const": "4k" } } }, "then": { "required": ["seed"] } }
  ]
}

Ogni ramo anyOf contiene soltanto required e significa «fornisci almeno uno di questi». Ogni ramo allOf è un if → then: if viene attivato da required oppure properties.<field>.const, then dichiara soltanto required e significa «se fornisci A devi fornire B».

oneOf, not, dependentSchemas e dependentRequired non compaiono mai nell'inputSchema di un modello: esprimono il vincolo ma non possono essere rappresentati in un modulo, quindi l'utente lo scoprirebbe soltanto come un 400 inspiegabile dopo l'invio. Implementare le due forme sopra copre ogni endpoint condizionale.

Ciclo di vita asincrono

queued -> running -> succeeded
                  -> failed
                  -> expired

createTask restituisce un ID di attività Spicy. Interroga recordInfo oppure ricevi un webhook Spicy firmato. queued e running non sono stati finali; gli altri sono finali. Le registrazioni storiche canceled restano leggibili per compatibilità, ma le nuove attività non hanno un'azione di annullamento. Attività asincrone è la fonte autorevole sugli stati.

Uno stato interno non finale sconosciuto del modello viene mappato a running fino a uno stato finale noto o alla scadenza assoluta della piattaforma. Un invio non idempotente con una conferma incerta non viene ripetuto alla cieca, evitando generazioni e addebiti duplicati.

Risposta ed errori unificati

Ogni API JSON nativa (/api/v1) usa la stessa struttura esterna; gli endpoint di compatibilità /v1 e /v1beta usano i formati dei rispettivi protocolli:

{
  "code": 200,
  "msg": "success",
  "data": {},
  "request_id": "req_01k3m8x9q2z4v7n5p6r8s0t1w2"
}

data è assente in caso di errore sincrono. Basa la logica su code, mai sul msg modificabile; usa request_id per l'assistenza. Un errore dopo la creazione dell'attività usa data.state: "failed" e un errorCode stabile. errorMessage è leggibile dalle persone: quando il servizio del modello ha riportato un motivo specifico, contiene quel motivo in inglese con nomi interni, indirizzi e dettagli dell'account rimossi; altrimenti è un messaggio della piattaforma nella tua lingua degli errori. Basa la logica su errorCode, mai su errorMessage.

Risultati e download

Un'attività riuscita elenca i propri file in output.assets[]. Ogni risorsa pronta include già un link di download:

{
  "assets": [
    {
      "key": "tasks/2026/08/31/job_01k3m8x9q2z4v7n5p6r8s0t1w3/asset_01.mp4",
      "url": "https://example.r2.cloudflarestorage.com/results/asset_01.mp4?X-Amz-Signature=SIGNATURE_FROM_RESPONSE",
      "expiresAt": "2026-08-31T10:20:00Z",
      "mime": "video/mp4",
      "durationSeconds": 8,
      "bytes": 1234567
    }
  ]
}

Scarica direttamente url, senza chiave API. Normalmente dura 20 minuti; leggi nuovamente l'attività per ottenerne uno nuovo finché il risultato è conservato (al massimo 14 giorni). Mentre un file viene ancora archiviato, la risorsa ha pending: true e nessun url; se l'archiviazione è fallita definitivamente, ha unavailable: true. key identifica il file per l'endpoint facoltativo download-url; non ti serve per scaricare. Tutti i link puntano allo storage di SpicyAPI.

Fatturazione al cliente

pricing, startingPrice e quantityField del catalogo e estimatedCost / cost dell'attività descrivono soltanto i prezzi al cliente. Gli importi sono stringhe decimali in USD. I dati aziendali interni sono fuori dal contratto pubblico e non compaiono mai in cataloghi, attività, webhook o log esportati.

Compatibilità e deprecazione

Modifiche che dovresti tollerare senza interrompere il funzionamento: un nuovo campo facoltativo, un nuovo campo di risposta che puoi ignorare oppure un'indicazione x-ui sconosciuta.

Un nuovo campo obbligatorio, un valore di enumerazione rimosso, un cambiamento di significato o tipo, un limite più restrittivo o un ID pubblico di modello modificato comportano una nuova versione del modello oppure una finestra di deprecazione annunciata. Gli ID pubblicati restano immutabili; le migrazioni usano un alias di compatibilità o un reindirizzamento esplicito.

Memorizza in cache il catalogo autenticato come descritto in Memorizzare il catalogo in cache. Non mantenere mai uno snapshot permanente dello schema né ripiegare su una pagina statica quando il catalogo aggiornato non contiene una voce utilizzabile.

In questa pagina