spicyapiDokumentacja
SDK
Treść główna

SDK dla Pythona

Oficjalne SDK SpicyAPI dla Pythona (spicyapi): instalacja, wycena i pierwsza generacja, wysyłanie plików z dysku, weryfikacja webhooków oraz wszystkie kody błędów.

spicyapi to oficjalne SDK SpicyAPI dla Pythona. Generowanie obrazów, wideo i dźwięku chowa za jednym obiektem klienta: dołącza twój klucz API, zamienia strukturę odpowiedzi w zwykłe słowniki, czeka na zakończenie zadania, rozsądnie wydłużając odstępy, wysyła pliki z dysku jednym wywołaniem i weryfikuje podpisy webhooków w stałym czasie.

Wymaga Pythona 3.11 lub nowszego i nie ma żadnych zależności w czasie działania. To celowe: ten pakiet trafia do drzewa zależności, które już utrzymujesz, a każde ograniczenie, jakie do niego dokłada, to kolejna okazja do konfliktu.

Czy to właściwe narzędzie?

Chcesz…Użyj
Wywoływać SpicyAPI z własnego kodu w PythonieTego SDK
Wywoływać je z Node.js albo TypeScriptuSDK dla TypeScriptu
Wywoływać je z Go, PHP albo JavySDK dla Go, SDK dla PHP albo SDK dla Javy
Generować z terminala, bez pisania koduCLI
Pozwolić, żeby asystent AI wywoływał SpicyAPI za ciebieSerwer MCP i Agent Skill
Korzystać z modelu czatu albo modelu tekstowegoOficjalnej biblioteki openai, anthropic albo google-genai skierowanej na SpicyAPI – zobacz Tekst i streaming

Instalacja

pip install spicyapi

Klucz trzymaj w zmiennej środowiskowej, żeby nigdy nie pojawił się w twoim kodzie ani w pliku historii powłoki:

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

Pierwszy wynik

Zapytaj o cenę, zdecyduj, utwórz zadanie, poczekaj, odczytaj pliki. Wycena jest bezpłatna i niczego nie blokuje.

import os, uuid
from spicyapi import SpicyClient, output_assets

client = SpicyClient()  # odczytuje SPICY_API_KEY ze zmiennej środowiskowej

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"])   # zdecyduj, zanim wydasz pieniądze

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):                  # funkcja modułu, nie metoda klienta
    print(asset["url"])

MODEL_ID_FROM_CATALOG to symbol zastępczy. Prawdziwy identyfikator bierz z uwierzytelnionego katalogu na żywo — client.list_models(), czyli GET /api/v1/models — a nigdy z pamięci ani ze starej strony: modele są dodawane, wstrzymywane i wycofywane. input_data buduj na podstawie inputSchema tego konkretnego modelu, które zwraca list_models(include_schema=True); każdy model przyjmuje inne pola.

Kwoty wracają jako dziesiętne łańcuchy znaków w dolarach amerykańskich, nigdy jako liczby zmiennoprzecinkowe, bo binarne liczby zmiennoprzecinkowe nie potrafią dokładnie zapisać większości kwot dziesiętnych. Porównuj je i sumuj przez decimal.Decimal. W tym API nigdzie nie ma kredytów ani punktów.

wait_for_terminal kończy się na każdym stanie końcowym. Stan końcowy to jeszcze nie stan udany — zanim sięgniesz po wynik, sprawdź final["state"].

Część endpointów odpowiada tekstem, a nie plikami. Gdy model tworzy transkrypcję albo opis, najpierw czytaj output_text(final); klient, który przegląda wyłącznie listę plików, uzna w pełni udane zadanie za takie, które niczego nie stworzyło.

Zacznij od pliku z dysku

Generowanie wideo z obrazu, podmiana osoby i edycja obrazu wymagają, żeby twój materiał najpierw trafił na naszą stronę. upload_file wykonuje wysyłkę w trzech krokach — pozwolenie na wysyłkę, PUT do magazynu, commit — w jednym wywołaniu i zwraca URI spicy://. To właśnie ten URI trafia do danych wejściowych.

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()),
)

Publicznie dostępny adres HTTPS możesz podać w danych wejściowych wprost i wtedy nie musisz niczego wysyłać. Limit dla obrazów to 10 MiB, dla dźwięku i wideo – 90 MiB; resztę opisuje strona Media.

Webhooki

verify_webhook jest funkcją modułu, więc obsługa żądania może z niej skorzystać bez tworzenia klienta. Porównuje w stałym czasie, a znacznik czasu sprawdza dopiero wtedy, gdy podpis okaże się prawidłowy.

from spicyapi import verify_webhook

delivery = verify_webhook(
    raw_body=request.body,                      # dokładnie te bajty, przed jakimkolwiek parsowaniem
    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"],
)

Weryfikuj surowe bajty. json.loads, a po nim json.dumps, zmienia je i podpis już nigdy się nie zgodzi. Dostarczenia są ponawiane, więc odsiewaj duplikaty po identyfikatorze dostarczenia. Pełny format dostarczenia i harmonogram ponowień opisuje strona Webhooki.

Błędy

Każde niepowodzenie zgłasza SpicyApiError z polami status, code, request_id i retry_after_seconds. Rozgałęziaj logikę po code, nigdy po treści komunikatu — komunikaty są tłumaczone, kody nie.

Status HTTP 503 dzielą między siebie trzy różne kody aplikacyjne, więc sam status HTTP nie wystarczy, żeby zdecydować, co zrobić:

KodCo to znaczyCo zrobić
40003przesłane bajty nie zgadzają się ze swoim pozwoleniem na wysyłkęzacznij od nowa, od świeżego pozwolenia
40004żadne wdrożenie nie obsługuje tej kombinacji parametrówzmień parametr wskazany w komunikacie
40201za niskie saldodoładuj konto
40901cena zmieniła się, zanim powstało zadaniewyceń ponownie, zachowując ten sam klucz idempotentności
503składnik, od którego zależymy, jest chwilowo niedostępnyodczekaj tyle, ile mówi Retry-After
50301model nie ma teraz działającego wdrożenia ani cenyodśwież katalog, nie bombarduj usługi
50302generacja synchroniczna nie powiodła się podczas przetwarzania i została zwróconaponów z nowym kluczem idempotentności

err.recovery zwraca tę samą wskazówkę w czasie działania programu. Kontaktując się ze wsparciem, podaj request_id. Wszystkie kody wymienia strona Błędy.

Dwie rzeczy, które oszczędzą ci pieniędzy

Miej jeden klucz idempotentności na jedno zgłoszenie. Używaj go przy każdym ponownym wysłaniu tego zgłoszenia, także po przekroczeniu czasu albo zerwaniu połączenia. Utracona odpowiedź nie dowodzi, że zadanie nie powstało — nowy klucz zamienia nieznany wynik w drugie płatne zadanie. Zobacz Idempotentność.

Za udane zadanie płacisz, nawet jeśli wynik cię rozczaruje. Gdy cena ma znaczenie, najpierw wyceń: quote_task niczego nie blokuje i niczego nie tworzy.

Czego ten pakiet nie robi

  • Modeli tekstowych. Mówią formatami OpenAI, Anthropic i Gemini, więc oficjalne biblioteki openai, anthropic i google-genai działają od ręki — skieruj je na https://api.spicyapi.ai/v1 z tym samym kluczem. Zobacz Tekst i streaming.
  • Aplikacji przeglądarkowych, mobilnych i desktopowych. Nigdy nie umieszczaj tego klucza w aplikacji: klucz wkompilowany w program kliencki jest kluczem publicznym. Wywołuj ze swojego serwera.
  • Wyboru modelu ani wypełniania jego pól. Pakiet podaje ci katalog i schemat każdego modelu; o tym, co wysłać, decydujesz ty.
  • Anulowania zadania. Przyjęte zadanie wykonuje się do końca. Zatrzymanie programu kończy tylko twoje czekanie.

Kod źródłowy

Pakiet jest na licencji MIT i powstaje otwarcie pod adresem github.com/spicyapi-ai/spicy-python. Jego README to najkrótsza kompletna wycieczka po kliencie; ta strona dokłada do tego pojęcia, które go otaczają.

Co dalej

Na tej stronie