Kontrakt Spicy Schema
Wspólna struktura żądań, standardowe pola, schemat formularza, cykl życia zadań asynchronicznych, błędy, przechowywanie wyników i zasady zgodności.
Spicy Schema to publiczny kontrakt dla każdego nowego modelu multimedialnego. Dodanie modelu zmienia jego model, inputSchema i cenę dla klienta; uwierzytelnianie, zadania, wyniki, błędy i pobieranie pozostają takie same.
To strona referencyjna. Większości integracji wystarczy Katalog modeli i schematy. Czytaj dalej, jeśli tworzysz formularz, walidator lub generator kodu na podstawie inputSchema i chcesz dokładnie wiedzieć, na czym możesz polegać.
Tylko katalog na żywo potwierdza możliwość wywołania
Ta strona określa strukturę kontraktu; nie stwierdza, że jakikolwiek model jest dostępny. Przed płatną operacją odczytaj uwierzytelnioną odpowiedź GET /api/v1/models i wymagaj zarówno enabled: true, jak i available: true. Pozycji planowanych lub wyłączonych nie można wywoływać.
Granica publicznego kontraktu
Publiczny identyfikator modelu nazywa jedną stabilną możliwość w postaci <publisher>/<model>/<task>. Wydawca to twórca modelu: autor lub organizacja badawcza, która za nim stoi. Edycja obrazów zawsze ma przyrostek edit, a wcześniej opublikowane identyfikatory pozostają akceptowane. Zawsze kopiuj rzeczywisty identyfikator z katalogu na żywo; MODEL_ID_FROM_CATALOG na tej stronie jest symbolem zastępczym.
Publiczne odpowiedzi, webhooki, błędy i linki pobierania używają wyłącznie własnych identyfikatorów, kodów błędów i adresów URL SpicyAPI. Nigdy nie zawierają szczegółów wewnętrznego przetwarzania, surowych odpowiedzi, surowych błędów ani wewnętrznych danych biznesowych. Wyniki są kopiowane do własnego magazynu SpicyAPI przed zwróceniem ich klientowi.
Wspólna struktura tworzenia zadania
{
"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"
}| Pole | Zasada |
|---|---|
model | Dokładna wartość dostępna obecnie do wywołania z uwierzytelnionego katalogu na żywo |
input | Musi odpowiadać aktualnemu inputSchema tej samej pozycji; nieznane pola są odrzucane |
callBackUrl | Opcjonalny publiczny adres HTTPS, na który trafia zakończone zadanie; zachowaj dokładnie tę wielkość liter. Zobacz Webhooki |
Powyższe input służy tylko jako ilustracja: o tym, które z tych pól model przyjmuje, decyduje wyłącznie jego własny inputSchema.
Standardowe pola
To samo pojęcie ma jedną nazwę w snake_case we wszystkich nowych endpointach. Tabela wymienia często spotykane pola, a nie wszystkie; pełną listą zawsze jest inputSchema danego modelu.
| Pojęcie | Pole | Typ |
|---|---|---|
| Prompt pozytywny | prompt | ciąg znaków |
| Prompt negatywny | negative_prompt | ciąg znaków |
| Obraz główny / końcowy | image_url / last_image_url | odwołanie do obrazu (poniżej) |
| Kilka obrazów wejściowych | image_urls | tablica odwołań do obrazów |
| Maska edycji | mask_url | odwołanie do obrazu |
| Główne wideo / audio | video_url / audio_url | publiczny adres HTTPS lub zatwierdzone URI spicy:// |
| Media referencyjne | reference_image_urls / reference_video_urls / reference_audio_urls | tablica odwołań |
| Czas trwania wyniku | duration_seconds | liczba lub liczba całkowita |
| Rozdzielczość / proporcje | resolution / aspect_ratio | udokumentowany zbiór wartości enum |
| Dokładny rozmiar wyniku | size (ustawienie wstępne) lub width / height | udokumentowany zbiór wartości enum / liczba całkowita |
| Liczba klatek na sekundę | fps | liczba całkowita |
| Natywny dźwięk | generate_audio | wartość logiczna |
| Ziarno losowania | seed | liczba całkowita |
| Wagi adapterów | loras lub high_noise_loras / low_noise_loras, gdy endpoint udostępnia etapy osobno | tablica obiektów |
| Liczba wyników | num_outputs | dodatnia liczba całkowita |
| Format kodowania | output_format | udokumentowany zbiór wartości enum |
| Rozmowa czatu | messages | tablica |
| Długość wyniku / próbkowanie | max_tokens / temperature | liczba całkowita / liczba |
Odwołanie do obrazu to publiczny adres HTTPS, zatwierdzone URI spicy:// z przesłanego pliku albo małe URI data:image/…;base64,…. Wideo i audio nie można przesyłać bezpośrednio w treści żądania. Zobacz Media.
Wpis wag adaptera określa jeden zestaw wag i siłę ich zastosowania. Nazwa pola jest stała, ale struktura wpisu już nie: to, co endpoint przyjmuje jako plik wag — adres URL czy klucz z wbudowanej biblioteki — jest ograniczone przez jego własny podschemat items. Odczytaj go zamiast zakładać jeden format. To samo dotyczy liczby wpisów i wymaganych pól wewnątrz każdego wpisu.
Pole specyficzne dla modelu istnieje tylko wtedy, gdy reprezentuje rzeczywistą możliwość, której nie opisuje już żadne standardowe pole, i jest nazywane według tej możliwości. Starszy endpoint może zachować wcześniejsze nazwy pól w aktualnym inputSchema; nowe endpointy ich nie kopiują.
inputSchema i adnotacje interfejsu
Każdy model używa JSON Schema 2020-12 w inputSchema. Ten sam schemat steruje walidacją serwera, formularzami Playground, przykładami i wycenami. Oficjalne SDK TypeScript nadaje statyczne typy wspólnym strukturom żądań i odpowiedzi; input każdego modelu pozostaje Record<string, unknown> i wymaga walidacji względem schematu na żywo, zamiast zakładania, że istnieją wygenerowane pola dla każdego modelu.
Ta strona nie utrzymuje tabel parametrów poszczególnych modeli. Parametry mają dokładnie jedno źródło: inputSchema zwracane przez GET /api/v1/models?includeSchema=1, które renderuje również Playground. Statyczna kopia przestaje odpowiadać rzeczywistości wraz ze zmianami modeli i nic nie wykryje tego rozjazdu. Aby zbudować z niego własną tabelę, zobacz Katalog modeli i schematy.
Każdy otrzymany schemat:
- ma korzeń
objecti odrzuca nieznane pola (additionalProperties: false); - określa
required, typy, wartości enum, zakresy, długości, limity tablic, formaty URI, wartości domyślne i zweryfikowane warunki; - zawiera dla każdej właściwości niepusty angielski
description; - pomija niezweryfikowane pola i wartości domyślne zamiast je zgadywać;
- wyraża warunki przez
anyOf/allOfna poziomie korzenia (poniżej), nigdy jedynie przez widoczność w interfejsie; - nie zawiera przełączników zmieniających wyłącznie wewnętrzne przetwarzanie ani przełączników filtrów treści.
Adnotacje prezentacji: x-ui
Metadane prezentacji nie są drugim schematem walidacji. Wszystkie znajdują się we własnym obiekcie x-ui danej właściwości; jego klucze mają zapis snake_case i należą do zamkniętego zbioru:
| Klucz | Znaczenie |
|---|---|
widget | kontrolka do wyrenderowania; wartości poniżej |
order | obowiązująca kolejność pól, od największej wartości; unikalna w obrębie endpointu |
label / placeholder | zastąpienie domyślnej etykiety; tekst zastępczy pola wejściowego |
rows | liczba wierszy pola tekstowego |
step / unit | krok liczbowy i przyrostek jednostki (s, px) |
accept / max_size_mb | filtr MIME i limit rozmiaru pojedynczego pliku dla kontrolek przesyłania |
advanced | pole należy do zwijanej sekcji zaawansowanej |
primary | główne pole wejściowe; przypięte na górze i nigdy niezwijane |
affects_price | zmiana tej wartości wymaga nowej wyceny |
visible_when | wyrażenie warunkowej widoczności |
enum_labels | przypisanie wartości enum do widocznej etykiety |
x-ui.widget ma jedną z trzynastu wartości: textarea, text, upload, multi-upload, select, radio, slider, number, switch, json, object-list, chat-messages, hidden. Kontrolka jest zawsze zgodna ze strukturą danych, dlatego renderer może bezpośrednio wybrać jej obsługę: select i radio zawsze mają enum; slider zawsze ma zarówno minimum, jak i maximum (nigdy wyłącznie exclusiveMinimum / exclusiveMaximum); switch zawsze ma typ boolean; multi-upload jest tablicą z items.type: string; object-list jest tablicą z items.type: object i items.properties, a każde podpole ma własne type i description; chat-messages jest tablicą; hidden oznacza, że pole nadal jest wysyłane, ale nie ma kontrolki.
Dla każdego pola tablicowego jego własne minItems / maxItems i podschemat items zawierają ograniczenia, których główna lista required nigdy nie wymienia, a serwer egzekwuje je tak samo jak resztę schematu. Pole object-list ma w items samodzielny, pełny schemat obiektu: ma własne required, własne additionalProperties: false oraz własny typ, zakres i default dla każdego podpola. Wartości domyślne działają również wewnątrz wpisów: pominięte podpole jest uzupełniane z default przed walidacją, więc podpole wymagane, ale mające wartość domyślną, jest w praktyce opcjonalne. Brak podpola bez wartości domyślnej jest odrzucany, tak samo jak nieznane podpole lub wartość poza jego zakresem.
400 dotyczące wartości wewnątrz tablicy wskazuje konkretny wpis — pole, indeks liczony od zera i podpole — zamiast całego żądania. Przekaż ten wskaźnik osobie, która ma poprawić dane: przy kilku przetwarzanych wpisach wskazanie tego z błędnym zakresem decyduje, czy wystarczy poprawka jednego wiersza, czy trzeba zawężać problem kolejnymi próbami.
Klient musi ignorować nieznane klucze prezentacji: dodanie klucza x-ui jest zmianą zgodną wstecznie.
{
"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" }
}Każdy description jest angielskim tekstem i można go wyświetlać bez zmian jako objaśnienie pola.
x-ui.affects_price: true wskazuje interfejsowi konieczność odświeżenia wyceny po zmianie pola. Nie jest wzorem cenowym i nigdy nie zastępuje katalogowych pricing ani quantityField. Główne x-pricing opisuje ten sam fakt od strony serwera: variantFields wymienia pola wybierające poziom ceny i zawsze jest podzbiorem pól affects_price: true, a billingMode określa sposób naliczania dla endpointu. Oba są wskazówkami; wiążącą kwotę zwracają katalog, wycena i zadanie. Sposób zapisu poziomów w pricing wyjaśnia Odczytywanie cen.
Pola warunkowe
Warunki mają dokładnie dwie postacie, obie na poziomie korzenia:
{
"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"] } }
]
}Każda gałąź anyOf zawiera tylko required i oznacza „podaj co najmniej jedno z tych pól”. Każda gałąź allOf jest jednym if → then: if sprawdza required lub properties.<field>.const, then deklaruje wyłącznie required, a całość oznacza „jeśli podasz A, musisz podać B”.
oneOf, not, dependentSchemas i dependentRequired nigdy nie występują w inputSchema modelu: opisują ograniczenie, ale nie da się go przedstawić w formularzu, więc użytkownik poznałby je dopiero przez niezrozumiałe 400 po wysłaniu. Obsługa dwóch powyższych postaci obejmuje każdy endpoint z polami warunkowymi.
Asynchroniczny cykl życia
queued -> running -> succeeded
-> failed
-> expiredcreateTask zwraca identyfikator zadania Spicy. Odpytuj recordInfo lub odbierz podpisany webhook Spicy. queued i running nie są stanami końcowymi; pozostałe są. Historyczne rekordy canceled pozostają dostępne do odczytu dla zachowania zgodności, ale nowe zadania nie mają operacji anulowania. Wiążący opis stanów znajdziesz w Zadaniach asynchronicznych.
Nieznany niekońcowy stan wewnątrz modelu jest mapowany na running aż do znanego stanu końcowego lub bezwzględnego terminu platformy. Nieidempotentne żądanie wysłania z niepewnym potwierdzeniem nie jest automatycznie powtarzane w ciemno, co zapobiega podwójnemu generowaniu i opłatom.
Wspólna odpowiedź i błędy
Każde natywne API JSON (/api/v1) używa tej samej struktury; endpointy zgodności /v1 i /v1beta używają struktur własnych protokołów:
{
"code": 200,
"msg": "success",
"data": {},
"request_id": "req_01k3m8x9q2z4v7n5p6r8s0t1w2"
}Przy synchronicznym błędzie nie ma data. Logikę programu opieraj na code, nigdy na zmiennym msg; do kontaktu ze wsparciem używaj request_id. Niepowodzenie po utworzeniu zadania używa data.state: "failed" i stabilnego errorCode. errorMessage jest przeznaczony do odczytu przez człowieka: gdy usługa modelu podała konkretny powód, jest to ten powód po angielsku, po usunięciu wewnętrznych nazw, adresów i danych konta; w przeciwnym razie jest to komunikat platformy w twoim języku błędów. Logikę programu opieraj na errorCode, nigdy na errorMessage.
Wyniki i pobieranie
Zadanie zakończone powodzeniem wymienia swoje pliki w output.assets[]. Każdy gotowy plik wynikowy zawiera już link pobierania:
{
"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
}
]
}Pobierz bezpośrednio url, bez klucza API. Zwykle jest ważny przez 20 minut; odczytaj zadanie ponownie, aby uzyskać nowy adres, dopóki wynik jest przechowywany (najwyżej 14 dni). Gdy plik nadal jest zapisywany, zasób ma pending: true i nie ma url; jeśli zapis ostatecznie się nie powiódł, ma unavailable: true. key identyfikuje plik dla opcjonalnego endpointu download-url; nie jest potrzebny do pobrania. Wszystkie linki prowadzą do własnego magazynu SpicyAPI.
Rozliczenia klienta
Katalogowe pricing, startingPrice, quantityField oraz estimatedCost / cost zadania opisują wyłącznie ceny dla klienta. Kwoty są ciągami znaków z dziesiętną wartością USD. Wewnętrzne dane biznesowe są poza publicznym kontraktem i nigdy nie pojawiają się w katalogach, zadaniach, webhookach ani eksportowanych logach.
Zgodność i wycofywanie
Zmiany, które należy tolerować bez zakłócenia działania: nowe pole opcjonalne, nowe pole odpowiedzi, które można zignorować, lub nieznana wskazówka x-ui.
Nowe pole wymagane, usunięcie wartości enum, zmiana znaczenia lub typu, zaostrzenie limitu albo zmiana publicznego identyfikatora modelu wiążą się z nową wersją modelu lub ogłoszonym okresem wycofywania. Opublikowane identyfikatory pozostają niezmienne; migracje używają aliasu zgodności lub jawnego przekierowania.
Przechowuj uwierzytelniony katalog w pamięci podręcznej zgodnie z Buforowaniem katalogu. Nigdy nie utrzymuj trwałej migawki schematu ani nie używaj statycznej strony jako źródła zastępczego, gdy katalog na żywo nie ma pozycji dostępnej do wywołania.
Limity żądań
Jak działają osobne limity odczytu i zapisu, co zużywa każdy z nich, jakie inne ograniczenia możesz napotkać i dlaczego współbieżność to osobna kwestia.
Nieodwracalność zadań i ponawianie
Dlaczego zaakceptowanego zadania generowania nie można anulować i jak bezpiecznie ponawiać zadania zakończone błędem lub po upływie terminu.

