spicyapiDocumentação
SDKs
Conteúdo principal

SDK para Python

O SDK oficial da SpicyAPI para Python (spicyapi) — instale, cote e faça a sua primeira geração, envie um arquivo local, verifique webhooks e consulte todos os códigos de erro.

O spicyapi é o SDK oficial para Python da SpicyAPI. Ele coloca a geração de imagem, vídeo e áudio atrás de um único objeto cliente: anexa a sua chave de API, transforma o envelope da resposta em dicionários comuns, espera uma tarefa terminar com pausas crescentes e sensatas entre as consultas, envia arquivos locais numa única chamada e verifica assinaturas de webhook em tempo constante.

Ele exige Python 3.11 ou mais recente e não tem nenhuma dependência de execução. Isso é de propósito: este pacote entra numa árvore de dependências que já é sua, e cada restrição que ele acrescenta é mais uma chance de conflito.

Esta é a ferramenta certa?

Você quer…Use
Chamar a SpicyAPI a partir do seu próprio código PythonEste SDK
Chamá-la a partir de Node.js ou TypeScriptO SDK para TypeScript
Chamá-la a partir de Go, PHP ou JavaO SDK para Go, PHP ou Java
Gerar conteúdo pelo terminal, sem escrever códigoA CLI
Deixar um assistente de IA chamar a SpicyAPI por vocêO servidor MCP e o Agent Skill
Usar um modelo de conversa ou de textoA biblioteca oficial openai, anthropic ou google-genai apontada para a SpicyAPI — veja Texto e streaming

Instalar

pip install spicyapi

Depois coloque a sua chave no ambiente, para que ela nunca apareça no seu código nem no arquivo de histórico do seu shell:

export SPICY_API_KEY="sk-spicy-..."

Seu primeiro resultado

Peça o preço, decida, crie a tarefa, espere, leia os arquivos. Cotar é grátis e não reserva nada.

import os, uuid
from spicyapi import SpicyClient, output_assets

client = SpicyClient()  # lê SPICY_API_KEY do ambiente

model = client.get_model("MODEL_ID_FROM_CATALOG")
quote = client.quote_task(model=model["model"], input_data={"prompt": "a lantern in fog"})
print(quote["estimatedCost"], quote["maxCharge"])   # decida antes de gastar

task = client.create_task(
    model=model["model"],
    input_data={"prompt": "a lantern in fog"},
    idempotency_key=str(uuid.uuid4()),
    quote_id=quote["quoteId"],
    expected_cost=quote["estimatedCost"],
)
final = client.wait_for_terminal(task["taskId"])
for asset in output_assets(final):                  # função do módulo, não um método
    print(asset["url"])

MODEL_ID_FROM_CATALOG é um marcador. Pegue um ID de verdade no catálogo autenticado — client.list_models(), que é GET /api/v1/models — e nunca de memória nem de uma página antiga: modelos são acrescentados, pausados e aposentados. Monte o input_data a partir do inputSchema daquele modelo, que list_models(include_schema=True) devolve; cada modelo aceita campos diferentes.

Os valores voltam como texto decimal em dólares americanos, nunca como float, porque números binários de ponto flutuante não guardam a maioria dos valores decimais com exatidão. Compare e some com decimal.Decimal. Não existem créditos nem pontos em lugar nenhum desta API.

wait_for_terminal retorna em qualquer estado terminal. Um estado terminal não é necessariamente um estado de sucesso — confira final["state"] antes de ler a saída.

Alguns endpoints respondem com texto, e não com arquivos. Leia primeiro output_text(final) quando o modelo produz uma transcrição ou uma legenda; um cliente que só percorre a lista de arquivos informa que uma tarefa perfeitamente bem-sucedida não produziu nada.

Começar por um arquivo local

Imagem para vídeo, troca de personagem e edição de imagem precisam do seu material do nosso lado antes de mais nada. O upload_file faz o envio de três etapas — ticket, PUT para o armazenamento e commit — numa única chamada e devolve uma URI spicy://. É essa URI que vai na entrada.

uploaded = client.upload_file("/path/to/reference.png")
task = client.create_task(
    model="MODEL_ID_FROM_CATALOG",
    input_data={"image": uploaded["uri"], "prompt": "slow dolly in"},
    idempotency_key=str(uuid.uuid4()),
)

Uma URL HTTPS acessível publicamente pode ir direto na entrada e não precisa de envio nenhum. Imagens são aceitas até 10 MiB; áudio e vídeo, até 90 MiB. O resto está em Mídia.

Webhooks

verify_webhook é uma função do módulo, então um handler de requisição pode usá-la sem montar um cliente. Ela compara em tempo constante e só confere o horário depois que a assinatura se mostra válida.

from spicyapi import verify_webhook

delivery = verify_webhook(
    raw_body=request.body,                      # os bytes exatos, antes de qualquer parsing
    signature=request.headers["X-Webhook-Signature"],
    timestamp=request.headers["X-Webhook-Timestamp"],
    payload_version=request.headers["X-Webhook-Payload-Version"],
    secret=os.environ["SPICY_WEBHOOK_SECRET"],
)

Verifique os bytes crus. Um json.loads seguido de json.dumps muda esses bytes, e a assinatura nunca mais vai bater. As entregas são repetidas, então elimine duplicatas pelo ID da entrega. O formato completo das entregas e o calendário de novas tentativas estão em Webhooks.

Erros

Toda falha levanta um SpicyApiError com status, code, request_id e retry_after_seconds. Decida pelo code, nunca pelo texto da mensagem — mensagens são traduzidas, códigos não.

O HTTP 503 é compartilhado por três códigos de negócio diferentes, então ler só o status HTTP não basta para decidir o que fazer:

codeO que significaO que fazer
40003os bytes enviados não correspondem ao ticket delesrecomece com um ticket novo
40004nenhuma implantação atende a essa combinação de parâmetrosmude o parâmetro citado na mensagem
40201saldo insuficienteadicione saldo
40901o preço mudou antes de a tarefa ser criadacote de novo, mantendo a mesma chave de idempotência
503uma dependência está indisponível por pouco tempoespere o que o Retry-After pedir
50301o modelo não tem, neste momento, implantação nem preço utilizáveisatualize o catálogo, sem insistir em rajada
50302uma geração síncrona falhou no processamento e foi estornadatente de novo com uma chave de idempotência nova

err.recovery devolve a mesma orientação em tempo de execução. Cite o request_id ao falar com o suporte. Todos os códigos estão listados em Erros.

Duas coisas que vão economizar o seu dinheiro

Use uma chave de idempotência por envio. Reaproveite-a em cada reenvio daquele envio, inclusive depois de um tempo esgotado ou de uma conexão que caiu. Uma resposta perdida não prova que a tarefa não foi criada — uma chave nova transforma um resultado desconhecido numa segunda tarefa paga. Veja Idempotência.

Uma tarefa que dá certo é cobrada, mesmo que o resultado decepcione. Cote antes quando o preço importar; quote_task não reserva nada e não cria nada.

O que este pacote não faz

  • Modelos de texto. Eles falam os formatos de rede da OpenAI, da Anthropic e do Gemini, então as bibliotecas oficiais openai, anthropic e google-genai já funcionam — aponte-as para https://api.spicyapi.ai/v1 com a mesma chave. Veja Texto e streaming.
  • Aplicativos de navegador, celular e desktop. Nunca distribua esta chave dentro de um aplicativo: uma chave compilada num cliente é uma chave pública. Chame a partir do seu servidor.
  • Escolher o modelo ou preencher os campos dele. O pacote entrega o catálogo e o schema de cada modelo; quem decide o que enviar é você.
  • Cancelar uma tarefa. Depois de aceita, ela vai até o fim. Encerrar o seu programa só interrompe a sua espera.

Código-fonte

O pacote tem licença MIT e é desenvolvido abertamente em github.com/spicyapi-ai/spicy-python. O README dele é o passeio completo mais curto pelo cliente; esta página acrescenta os conceitos em volta.

Próximos passos

Nesta página