Contrato Spicy Schema
Envelope compartilhado de solicitações, campos canônicos, schema de formulário, ciclo assíncrono, erros, armazenamento e regras de compatibilidade.
Spicy Schema é o contrato público de todos os novos modelos de mídia. Adicionar um modelo muda seu model, seu inputSchema e o preço para o cliente; autenticação, tarefas, resultados, erros e downloads permanecem iguais.
Esta é uma página de referência. A maioria das integrações só precisa de Catálogo de modelos e schemas. Continue se você está criando um formulário, um validador ou um gerador de código a partir de inputSchema e quer saber exatamente com o que pode contar.
Somente o catálogo em tempo real comprova que um modelo pode ser chamado
Esta página define o formato do contrato; ela não afirma que algum modelo esteja disponível. Antes de operações pagas, consulte a resposta autenticada de GET /api/v1/models e exija tanto enabled: true quanto available: true. Entradas planejadas ou desativadas não podem ser chamadas.
Limites do contrato público
Um ID público de modelo identifica uma capacidade estável no formato <publisher>/<model>/<task>. O criador é o autor ou a organização de pesquisa responsável pelo modelo. A edição de imagem sempre usa o sufixo edit, e identificadores publicados anteriormente continuam sendo aceitos. Sempre copie um ID real do catálogo em tempo real; MODEL_ID_FROM_CATALOG nesta página é um marcador.
Respostas públicas, webhooks, erros e downloads usam somente identificadores, códigos de erro e URLs da própria SpicyAPI. Nunca incluem detalhes internos de processamento, respostas brutas, erros brutos ou dados comerciais internos. Os resultados são copiados para o armazenamento da própria SpicyAPI antes de serem retornados.
Envelope unificado de criação
{
"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"
}| Campo | Regra |
|---|---|
model | Valor exato e disponível para chamadas no catálogo autenticado em tempo real |
input | Precisa atender ao inputSchema atual do mesmo item; campos desconhecidos são recusados |
callBackUrl | Endereço público HTTPS opcional que recebe a tarefa concluída; mantenha exatamente estas maiúsculas e minúsculas. Veja Webhooks |
O input acima é ilustrativo: somente o inputSchema do próprio modelo define quais desses campos ele aceita.
Campos canônicos
O mesmo conceito usa um único nome em snake_case em todos os novos endpoints. Esta tabela reúne campos comuns, não todos eles; a lista completa sempre está no inputSchema do modelo.
| Conceito | Campo | Tipo |
|---|---|---|
| Prompt positivo | prompt | String |
| Prompt negativo | negative_prompt | String |
| Imagem principal / final | image_url / last_image_url | Referência de imagem; veja abaixo |
| Várias imagens de entrada | image_urls | Lista de referências de imagem |
| Máscara de edição | mask_url | Referência de imagem |
| Vídeo / áudio principal | video_url / audio_url | URL HTTPS pública ou URI spicy:// confirmado |
| Mídia de referência | reference_image_urls / reference_video_urls / reference_audio_urls | Lista de referências |
| Duração da saída | duration_seconds | Número ou inteiro |
| Resolução / proporção | resolution / aspect_ratio | Enumeração documentada |
| Tamanho exato da saída | size (uma opção predefinida) ou width / height | Enumeração documentada / inteiro |
| Taxa de quadros | fps | Inteiro |
| Áudio nativo | generate_audio | Booleano |
| Semente aleatória | seed | Inteiro |
| Pesos de adaptadores | loras ou high_noise_loras / low_noise_loras quando um endpoint expõe suas etapas separadamente | Lista de objetos |
| Quantidade de saídas | num_outputs | Inteiro positivo |
| Codificação | output_format | Enumeração documentada |
| Conversa de chat | messages | Lista |
| Comprimento da saída / amostragem | max_tokens / temperature | Inteiro / número |
Uma referência de imagem é uma URL HTTPS pública, um URI spicy:// confirmado após upload ou um pequeno URI data:image/…;base64,…. Vídeo e áudio não podem ser enviados diretamente no corpo como dados inline. Veja Mídia.
Uma entrada de pesos de adaptadores identifica um conjunto de pesos e a intensidade de aplicação. O nome do campo é fixo, mas o formato da entrada não: o que um endpoint aceita para um arquivo de pesos, uma URL ou uma chave de uma biblioteca integrada, é restringido pelo subschema items do próprio endpoint. Consulte-o em vez de presumir um formato. O mesmo vale para a quantidade máxima de entradas e para os subcampos obrigatórios.
Um campo específico de modelo só existe quando representa uma capacidade real não coberta por um campo canônico e recebe um nome baseado nessa capacidade. Um endpoint antigo pode manter nomes anteriores em seu inputSchema em tempo real; os novos não os copiam.
inputSchema e anotações de interface
Todo modelo usa JSON Schema 2020-12 em inputSchema. O mesmo schema orienta a validação no servidor, os formulários do Playground, os exemplos e os orçamentos. O SDK oficial de TypeScript oferece tipos estáticos para os envelopes comuns de solicitação e resposta; o input de cada modelo continua sendo Record<string, unknown> e precisa ser validado com o schema em tempo real, em vez de presumir a existência de campos gerados por modelo.
Este site não mantém tabelas estáticas de parâmetros por modelo. Os parâmetros têm uma única fonte: o inputSchema retornado por GET /api/v1/models?includeSchema=1, também usado pelo Playground. Uma cópia fixa fica desatualizada conforme os modelos mudam, sem que nada identifique essa divergência. Para criar sua própria tabela, veja Catálogo de modelos e schemas.
Todo schema recebido:
- tem raiz
objecte recusa campos desconhecidos (additionalProperties: false); - declara
required, tipos, enumerações, intervalos, comprimentos, limites de listas, formatos de URI, valores padrão e condições verificadas; - fornece uma
descriptionnão vazia em inglês para cada propriedade; - omite campos e valores padrão não verificados, em vez de adivinhá-los;
- expressa condições por
anyOf/allOfna raiz, explicados abaixo, nunca apenas pela visibilidade na interface; - não contém opções que só alteram o processamento interno nem opções de filtro de conteúdo.
Anotações de apresentação: x-ui
Os metadados de apresentação não são um segundo schema de validação. Todos ficam no objeto x-ui da própria propriedade, com chaves em snake_case escolhidas de um conjunto fechado:
| Chave | Significado |
|---|---|
widget | Controle a renderizar; valores abaixo |
order | A ordem dos campos, em ordem decrescente, única em cada endpoint |
label / placeholder | Substituição do rótulo padrão; texto de exemplo da entrada |
rows | Quantidade de linhas da área de texto |
step / unit | Passo numérico e sufixo da unidade (s, px) |
accept / max_size_mb | Filtro MIME e tamanho máximo por arquivo nos controles de upload |
advanced | Deve ficar em uma seção avançada recolhida |
primary | Entrada principal; fixada no topo e nunca recolhida |
affects_price | Alterar o valor exige um novo orçamento |
visible_when | Expressão de visibilidade condicional |
enum_labels | Correspondência de valor de enumeração para rótulo de exibição |
x-ui.widget aceita um de treze valores: textarea, text, upload, multi-upload, select, radio, slider, number, switch, json, object-list, chat-messages, hidden. O controle sempre corresponde ao formato dos dados, de modo que um renderizador pode usá-lo diretamente para decidir o componente: select e radio sempre têm um enum; slider sempre tem minimum e maximum, nunca apenas exclusiveMinimum / exclusiveMaximum; switch é sempre um boolean; multi-upload é uma lista com items.type: string; object-list é uma lista com items.type: object e items.properties, e cada subcampo tem seu type e sua description; chat-messages é uma lista; hidden indica que o campo ainda é enviado, mas não tem controle visível.
Em qualquer campo de lista, o minItems / maxItems da própria lista e seu subschema items contêm restrições que a lista required da raiz não menciona. O servidor as aplica da mesma forma que as demais regras do schema. Um object-list tem em items um schema de objeto completo: tem seu próprio required, seu próprio additionalProperties: false e tipo, intervalo e default para cada subcampo. Os valores padrão também são aplicados dentro dessas entradas: um subcampo omitido recebe seu default antes da validação, de modo que um subcampo obrigatório com valor padrão é, na prática, opcional. Um subcampo sem valor padrão é recusado quando ausente, assim como um subcampo desconhecido ou um valor fora do intervalo permitido.
Um 400 causado por um valor dentro de uma lista aponta para a entrada exata, com campo, índice baseado em zero e subcampo, e não para a solicitação inteira. Passe essa indicação à pessoa responsável pela correção: com várias entradas em processamento, saber qual está fora do intervalo faz a diferença entre corrigir uma linha e procurar o erro por eliminação.
Os clientes devem ignorar chaves de apresentação desconhecidas: adicionar uma chave de x-ui é uma mudança compatível com versões anteriores.
{
"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" }
}Toda description é um texto em inglês e pode ser exibida sem alterações como ajuda do campo.
x-ui.affects_price: true orienta a interface a atualizar o orçamento após uma mudança no campo. Não é uma fórmula de preço e nunca substitui o pricing ou o quantityField do catálogo. O x-pricing na raiz é a representação dessa mesma informação no servidor: variantFields lista os campos que selecionam uma faixa de preço e sempre é um subconjunto dos campos com affects_price: true; billingMode indica como o endpoint é cobrado. Ambos são orientações; o valor oficial é o retornado pelo catálogo, pelo orçamento e pela tarefa. A representação das faixas em pricing está em Como interpretar preços.
Campos condicionais
As condições têm exatamente dois formatos, ambos na raiz:
{
"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"] } }
]
}Cada condição de anyOf contém somente required e significa “forneça pelo menos um destes”. Cada condição de allOf é um if → then: if é ativado por required ou properties.<field>.const; then declara somente required e significa “se fornecer A, você precisa fornecer B”.
oneOf, not, dependentSchemas e dependentRequired nunca aparecem no inputSchema de um modelo: expressam a restrição, mas não podem ser representados como formulário. O usuário só descobriria a regra ao receber um erro 400 inexplicável após enviar. Implementar os dois formatos acima cobre todos os endpoints condicionais.
Ciclo de vida assíncrono
queued -> running -> succeeded
-> failed
-> expiredcreateTask retorna um ID de tarefa Spicy. Consulte recordInfo ou receba um webhook Spicy assinado. queued e running não são estados finais; os demais são. Registros históricos canceled continuam legíveis por compatibilidade, mas novas tarefas não oferecem ação de cancelamento. Tarefas assíncronas é a referência sobre os estados.
Um estado interno não final e desconhecido de um modelo é convertido em running até um estado final conhecido ou até o prazo absoluto da plataforma. Um envio não idempotente cuja confirmação é incerta não é repetido sem verificação, evitando geração e cobrança duplicadas.
Respostas e erros unificados
Toda API JSON nativa (/api/v1) usa o mesmo envelope; os endpoints de compatibilidade /v1 e /v1beta usam os formatos dos respectivos protocolos:
{
"code": 200,
"msg": "success",
"data": {},
"request_id": "req_01k3m8x9q2z4v7n5p6r8s0t1w2"
}data não aparece em falhas síncronas. Baseie a lógica em code, nunca no msg, que pode mudar; use request_id ao pedir suporte. Uma falha após a criação da tarefa usa data.state: "failed" e um errorCode estável. errorMessage é legível por humanos: quando o serviço do modelo informa um motivo específico, a mensagem apresenta esse motivo em inglês, sem nomes, endereços ou dados de conta internos; caso contrário, é uma mensagem da plataforma no seu idioma de erros. Baseie a lógica em errorCode, nunca em errorMessage.
Resultados e downloads
Uma tarefa bem-sucedida lista seus arquivos em output.assets[]. Cada arquivo pronto já contém um link de 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
}
]
}Baixe url diretamente, sem sua chave de API. A URL normalmente dura 20 minutos; consulte a tarefa novamente para obter outra enquanto o resultado estiver retido, por no máximo 14 dias. Enquanto o arquivo ainda está sendo armazenado, o item tem pending: true e não tem url; se o armazenamento falhar definitivamente, tem unavailable: true. key identifica o arquivo para o endpoint opcional download-url; você não precisa dela para baixar. Todos os links apontam para o armazenamento da própria SpicyAPI.
Faturamento do cliente
pricing, startingPrice e quantityField do catálogo e estimatedCost / cost da tarefa descrevem apenas os preços para o cliente. Os valores são strings decimais em USD. Dados comerciais internos ficam fora do contrato público e nunca aparecem em catálogos, tarefas, webhooks ou logs exportados.
Compatibilidade e descontinuação
Mudanças que seu cliente deve tolerar sem falhar: um novo campo opcional, um novo campo de resposta que pode ser ignorado ou uma indicação de x-ui desconhecida.
Um novo campo obrigatório, a remoção de um valor de enumeração, uma mudança de significado ou tipo, um limite mais restrito ou a alteração de um ID público de modelo vêm acompanhados de uma nova versão do modelo ou de um prazo anunciado de descontinuação. IDs publicados permanecem imutáveis; migrações usam um alias de compatibilidade ou um redirecionamento explícito.
Mantenha o catálogo autenticado em cache conforme Cache do catálogo. Nunca mantenha uma cópia permanente do schema nem use uma página estática como alternativa quando o catálogo em tempo real não tiver nenhum item disponível para chamadas.
Limites de solicitações
Como funcionam os limites de leitura e escrita, quais chamadas contam em cada um, outros limites possíveis e a diferença em relação à concorrência.
Compromisso da tarefa e novas tentativas
Por que uma tarefa de geração aceita não pode ser cancelada e como repetir com segurança tarefas que falharam ou expiraram.

