Контракт Spicy Schema
Общий формат запросов, единые поля, схема форм, асинхронный жизненный цикл, ошибки, хранение результатов и правила совместимости.
Spicy Schema — публичный контракт для каждой новой медиамодели. При добавлении модели меняются её model, inputSchema и цена для клиента; аутентификация, задачи, результаты, ошибки и скачивание остаются одинаковыми.
Это справочная страница. Для большинства интеграций достаточно раздела Каталог моделей и схемы. Продолжайте чтение, если строите форму, валидатор или генератор кода на основе inputSchema и хотите точно понимать, на что можно опираться.
Доступность вызова подтверждает только актуальный каталог
Эта страница определяет форму контракта, но не утверждает, что какая-либо модель уже доступна. Перед платной работой прочитайте ответ авторизованного GET /api/v1/models и проверьте одновременно enabled: true и available: true. Запланированные или отключённые записи вызвать нельзя.
Публичная граница
Публичный ID модели обозначает одну стабильную возможность в формате <publisher>/<model>/<task>. Разработчик — автор или исследовательская организация, создавшие модель. Редактирование изображений всегда использует суффикс edit; ранее опубликованные идентификаторы продолжают приниматься. Всегда копируйте настоящий ID из актуального каталога; MODEL_ID_FROM_CATALOG на этой странице — заполнитель.
Публичные ответы, вебхуки, ошибки и ссылки для скачивания используют только собственные идентификаторы, коды ошибок и URL SpicyAPI. Они никогда не содержат внутренних деталей обработки, необработанных ответов и ошибок или внутренних коммерческих данных. Перед выдачей результатов они копируются в собственное хранилище SpicyAPI.
Единый формат создания задачи
{
"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"
}| Поле | Правило |
|---|---|
model | Точное значение из актуального авторизованного каталога, которое сейчас можно вызвать |
input | Должен соответствовать текущей inputSchema той же записи; неизвестные поля отклоняются |
callBackUrl | Необязательный публичный адрес HTTPS, получающий завершённую задачу; регистр букв должен быть именно таким. См. Вебхуки |
Приведённый выше input — иллюстрация: какие из этих полей принимает модель, определяет только её собственная inputSchema.
Единые поля
Одна и та же сущность использует одно имя в snake_case на всех новых эндпоинтах. Таблица перечисляет распространённые поля, а не все; полный список всегда содержится в inputSchema модели.
| Понятие | Поле | Тип |
|---|---|---|
| Позитивный промпт | prompt | строка |
| Негативный промпт | negative_prompt | строка |
| Основное / финальное изображение | image_url / last_image_url | ссылка на изображение (см. ниже) |
| Несколько входных изображений | image_urls | массив ссылок на изображения |
| Маска редактирования | mask_url | ссылка на изображение |
| Основное видео / аудио | video_url / audio_url | публичный URL HTTPS или подтверждённый URI spicy:// |
| Референсные медиафайлы | reference_image_urls / reference_video_urls / reference_audio_urls | массив ссылок |
| Длительность результата | duration_seconds | число или целое число |
| Разрешение / соотношение сторон | resolution / aspect_ratio | документированное перечисление |
| Точный размер результата | size (предустановка) или width / height | документированное перечисление / целое число |
| Частота кадров | fps | целое число |
| Генерация встроенного аудио | generate_audio | логическое значение |
| Начальное значение генератора случайных чисел | seed | целое число |
| Веса адаптеров | loras или high_noise_loras / low_noise_loras, если эндпоинт предоставляет отдельные стадии | массив объектов |
| Число результатов | num_outputs | положительное целое число |
| Формат кодирования | output_format | документированное перечисление |
| Чат-переписка | messages | массив |
| Длина ответа / сэмплирование | max_tokens / temperature | целое число / число |
Ссылка на изображение — публичный URL HTTPS, подтверждённый URI spicy:// загруженного файла или небольшой URI data:image/…;base64,…. Видео и аудио нельзя передавать непосредственно в запросе. См. Медиафайлы.
Запись весов адаптера указывает набор весов и силу его применения. Название поля фиксировано, а формат записи — нет: что эндпоинт принимает для файла весов — URL или ключ из встроенной библиотеки, — определяется его собственной подсхемой items. Прочитайте её, не предполагая заранее один формат. То же касается максимального числа записей и обязательных вложенных полей.
Специальное поле модели существует только для реальной возможности, которую ещё не охватывает ни одно единое поле, и называется по этой возможности. Старый эндпоинт может сохранять прежние названия в своей актуальной inputSchema; новые эндпоинты их не копируют.
inputSchema и аннотации интерфейса
Каждая модель использует JSON Schema 2020-12 в inputSchema. Одна и та же схема определяет серверную валидацию, формы Playground, примеры и расчёт цены. Официальный TypeScript SDK статически типизирует общие форматы запросов и ответов; input каждой модели остаётся Record<string, unknown> и должен проверяться по актуальной схеме. Не следует предполагать, что SDK генерирует отдельные поля для каждой модели.
На этом сайте нет отдельной статической таблицы параметров для каждой модели. У параметров ровно один источник: inputSchema из GET /api/v1/models?includeSchema=1, которую отображает и Playground. Статическая копия расходится с действительностью по мере изменения моделей, и это расхождение ничто не обнаружит. Как построить собственную таблицу — в разделе Каталог моделей и схемы.
Каждая полученная схема:
- имеет корень типа
objectи отклоняет неизвестные поля (additionalProperties: false); - задаёт
required, типы, перечисления, диапазоны, длины, ограничения массивов, форматы URI, значения по умолчанию и проверенные условия; - содержит непустое английское
descriptionдля каждого свойства; - не включает непроверенные поля и значения по умолчанию вместо того, чтобы их угадывать;
- выражает условия через корневые
anyOf/allOf(ниже), а не только через видимость в интерфейсе; - не содержит переключателей, меняющих лишь внутреннюю обработку, и переключателей фильтрации контента.
Аннотации отображения: x-ui
Метаданные отображения — не вторая схема валидации. Все они находятся в собственном объекте x-ui свойства; его ключи написаны в snake_case и принадлежат закрытому набору:
| Ключ | Значение |
|---|---|
widget | элемент управления для отображения; значения ниже |
order | единственный порядок полей: сначала большие значения; уникален внутри эндпоинта |
label / placeholder | замена стандартной подписи; текст-заполнитель поля |
rows | число строк многострочного поля |
step / unit | шаг числа и суффикс единицы (s, px) |
accept / max_size_mb | фильтр MIME и максимальный размер одного файла для элементов загрузки |
advanced | поле относится к свёрнутому разделу дополнительных настроек |
primary | основное поле; закреплено сверху и никогда не сворачивается |
affects_price | изменение значения требует нового расчёта цены |
visible_when | выражение условной видимости |
enum_labels | соответствие значения перечисления отображаемой подписи |
x-ui.widget принимает одно из тринадцати значений: textarea, text, upload, multi-upload, select, radio, slider, number, switch, json, object-list, chat-messages, hidden. Виджет всегда согласован с форматом данных, поэтому компонент отображения может выбирать обработку прямо по нему: select и radio всегда содержат enum; slider — одновременно minimum и maximum (никогда только exclusiveMinimum / exclusiveMaximum); switch всегда имеет тип boolean; multi-upload — массив с items.type: string; object-list — массив с items.type: object и items.properties, где каждое вложенное поле имеет собственные type и description; chat-messages — массив; hidden означает, что поле передаётся, но не имеет элемента управления.
Для любого массива его собственные minItems / maxItems и подсхема items содержат ограничения, о которых корневой список required ничего не говорит. Сервер применяет их так же, как остальные правила схемы. У object-list подсхема items сама является полной схемой объекта: у неё свои required, additionalProperties: false, тип, диапазон и default для каждого вложенного поля. Значения по умолчанию действуют и внутри записей: пропущенное вложенное поле заполняется из своего default до валидации, поэтому обязательное поле со значением по умолчанию фактически можно не передавать. Поле без значения по умолчанию при отсутствии отклоняется, как и неизвестное вложенное поле или значение за пределами его диапазона.
Ошибка 400 для значения внутри массива указывает точную запись: поле, индекс с нуля и вложенное поле, а не запрос в целом. Передавайте этот указатель тому, кто должен исправить данные. При нескольких записях понимание, какая именно выходит за диапазон, позволяет исправить одну строку вместо последовательного поиска причины.
Клиенты должны игнорировать неизвестные ключи отображения: добавление ключа x-ui обратно совместимо.
{
"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" }
}Каждое description — английский текст, который можно показывать без изменений как подсказку к полю.
x-ui.affects_price: true сообщает интерфейсу, что после изменения поля нужно обновить расчёт цены. Это не формула цены, и она никогда не заменяет каталожные pricing или quantityField. Корневой x-pricing отражает тот же факт на стороне сервера: variantFields перечисляет поля, выбирающие ценовую категорию, и всегда является подмножеством полей с affects_price: true; billingMode указывает способ учёта использования эндпоинта. Оба значения — подсказки; определяющая сумма возвращается каталогом, расчётом цены и задачей. Как категории представлены в pricing, описано в разделе Как читать цены.
Условные поля
Условия имеют ровно две формы, обе на уровне корня:
{
"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"] } }
]
}Каждая ветвь anyOf содержит только required и означает «передайте хотя бы одно из этих полей». Каждая ветвь allOf — одно условие if → then: if срабатывает по required или properties.<field>.const, а then задаёт только required. Это означает «если передаёте A, нужно передать B».
oneOf, not, dependentSchemas и dependentRequired никогда не появляются в inputSchema модели: они выражают ограничение, но его нельзя отобразить в форме. Поэтому пользователь узнал бы о нём лишь после отправки, получив непонятный 400. Реализация двух форм выше охватывает все эндпоинты с условиями.
Асинхронный жизненный цикл
queued -> running -> succeeded
-> failed
-> expiredcreateTask возвращает ID задачи Spicy. Опрашивайте recordInfo или получайте подписанный вебхук Spicy. queued и running — промежуточные состояния; остальные — конечные. Исторические записи canceled остаются доступными для чтения ради совместимости, но новые задачи нельзя отменить. Определяющее описание состояний находится в разделе Асинхронные задачи.
Неизвестное промежуточное состояние модели отображается как running до получения известного конечного состояния или наступления абсолютного крайнего срока платформы. Неидемпотентный запрос с неопределённым подтверждением принятия не отправляется повторно вслепую, что предотвращает дублирование генерации и оплаты.
Единый ответ и ошибки
Все нативные JSON API (/api/v1) используют общий формат; эндпоинты совместимости /v1 и /v1beta — собственные форматы своих протоколов:
{
"code": 200,
"msg": "success",
"data": {},
"request_id": "req_01k3m8x9q2z4v7n5p6r8s0t1w2"
}При синхронной ошибке data отсутствует. Обрабатывайте code, никогда не опираясь на изменяемый msg; для поддержки используйте request_id. Ошибка после создания задачи использует data.state: "failed" и стабильный errorCode. Поле errorMessage предназначено для человека: если сервис модели сообщил конкретную причину, это та же причина на английском с удалёнными внутренними именами, адресами и данными аккаунтов. Иначе это сообщение платформы на вашем языке ошибок. Обрабатывайте errorCode, а не errorMessage.
Результаты и скачивание
Успешная задача перечисляет файлы в output.assets[]. Каждый готовый файл уже содержит ссылку для скачивания:
{
"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
}
]
}Скачивайте url напрямую, без API-ключа. Обычно ссылка действует 20 минут; перечитайте задачу, чтобы получить новую, пока результат хранится (не более 14 дней). Пока файл ещё сохраняется, у него есть pending: true и нет url; если сохранить его окончательно не удалось, он имеет unavailable: true. Поле key определяет файл для необязательного эндпоинта download-url; для скачивания оно не требуется. Все ссылки ведут в собственное хранилище SpicyAPI.
Оплата клиентом
Каталожные pricing, startingPrice, quantityField и поля задачи estimatedCost / cost описывают только цену для клиента. Суммы — десятичные строки в USD. Внутренние коммерческие данные находятся за пределами публичного контракта и никогда не попадают в каталоги, задачи, вебхуки или экспортированные логи.
Совместимость и прекращение поддержки
Изменения, которые клиент должен переносить без сбоев: новое необязательное поле, новое поле ответа, которое можно игнорировать, или неизвестная подсказка x-ui.
Новое обязательное поле, удаление значения перечисления, изменение смысла или типа, более строгое ограничение либо изменение публичного ID модели сопровождаются новой версией модели или объявленным периодом прекращения поддержки. Опубликованные ID неизменны; миграции используют совместимый псевдоним или явное перенаправление.
Кешируйте авторизованный каталог, как описано в разделе Кеширование каталога. Не храните вечный снимок схемы и не подменяйте каталог статической страницей, если в актуальном каталоге нет доступной для вызова записи.
Ограничения частоты запросов
Как работают отдельные лимиты чтения и записи, какие запросы их расходуют, с какими другими ограничениями можно столкнуться и почему число параллельных задач — отдельный вопрос.
Принятые задачи и повторные попытки
Почему принятую задачу генерации нельзя отменить и как безопасно повторять неудачные или истёкшие задачи.

