spicyapi-com Core API
The Core API from spicyapi-com — 3 operation(s) for core.
The Core API from spicyapi-com — 3 operation(s) for core.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/spicyapi-com:spicyapi-com-core-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Spicy Core API
version: 1.0.0
description: 'Spicy API (also written SpicyAPI) is one REST API for uncensored image, image-editing, video, video-editing, speech, live voice call, transcription, embedding and chat generation, sold per generation from a prepaid US-dollar balance: no subscription, no GPUs to run. It is OpenAI-compatible (point the OpenAI SDK at https://api.spicyapi.com/v1 with a Spicy API key) and includes ready-made sex actions for video and role-play companion models. It has been at spicyapi.com since June 2025, is operated by Wayfinity Ltd, and is not affiliated with spicyapi.ai, an unrelated model aggregator. Images from $0.06, video from $0.05 per second. OPENAI-COMPATIBLE: point the OpenAI SDK at https://api.spicyapi.com/v1 with a Spicy API key; client.images.generate maps onto POST /v1/images/generations and client.chat.completions.create onto POST /v1/chat/completions (streaming included). client.embeddings.create maps onto POST /v1/embeddings and client.audio.transcriptions.create onto POST /v1/audio/transcriptions. Image edits take JSON with image_url (not the SDK''s multipart upload) and video (generations, edits, motion transfer) is a plain HTTP task you poll. Every response carries cost_usd, the exact amount debited. Prompts are screened before any charge (422, never billed); failed generations are refunded. Sandbox keys (created with sandbox: true) answer every endpoint from fixtures flagged sandbox: true and bill nothing. Machine-readable overview: https://www.spicyapi.com/llms.txt. MCP server for agents: https://www.spicyapi.com/api/mcp.'
contact:
name: Spicy API support
email: contact@spicyapi.com
url: https://www.spicyapi.com/docs
termsOfService: https://www.spicyapi.com/terms-of-service
servers:
- url: https://api.spicyapi.com
description: Public API host (also reachable at https://www.spicyapi.com/api).
tags:
- name: Core
paths:
/v1/models:
get:
operationId: listModels
summary: List Models
description: 'List every model available to your account. Returns the live catalogue: ids, pricing, limits and what each model accepts. Video models also carry `inputs`: which of first frame, last frame, reference images, clip and audio the model takes, the audio mode (driving or reference) and `combinations`, the valid input combinations in plain sentences. Build video requests from it; the same rules are listed under Input combinations on `POST /v1/videos/generations`. Kind-specific blocks: `speech` on speech models (voices, tags, streaming), `video_edit` on `POST /v1/videos/edits` models, `realtime` on live-call models, plus the flags `silent` (the video never has sound) and `bills_input_video_seconds` (an input `video_url` clip is billed per second too).'
tags:
- Core
security:
- apiKey: []
responses:
'200':
description: The models your key can call.
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
id:
type: string
description: The model id you pass as `model`.
kind:
type: string
description: One of `image`, `image-edit`, `video`, `video-edit`, `chat`, `speech`, `realtime`, `transcription`, `embedding`.
label:
type: string
description: Human-readable name.
description:
type: string
description: What the model is good for.
featured:
type: boolean
description: Reserved for highlighted models; false on every current model.
requires_image:
type: boolean
description: True when the model needs an `image_url` input.
accepts_image:
type: boolean
description: True when `image_url` is allowed. False on pure text-to-video models, which reject one.
pricing:
type: object
description: 'Unit and USD rate. `unit: "image"` with `usd`; `unit: "second"` with `usd_by_resolution` (video and video edits, keyed by resolution, or by `standard` / `pro` quality on motion transfer); `unit: "10K characters"` with `usd_per_10k_chars` (speech); `unit: "minute"` with `usd_per_minute` (transcription, billed by the second); `unit: "1M tokens"` with `usd_input` and `usd_output` (chat, embeddings), plus `usd_image` on image embeddings and `usd_audio_input` / `usd_audio_output` on live calls.'
accepts_reference:
type: boolean
description: True when the video model takes `character` and `reference_image_urls` (`spicy-character-video-1`, `spicy-motion-3`, `spicy-motion-3-fast`, `spicy-cinema-1-character`).
limits:
type: object
description: 'What the model accepts: `sizes` and `maxOutputs` on image models (6 on Spicy Image 1, 12 on Spicy Image 2 in set mode); `resolutions`, `minDuration`, `maxDuration`, `aspectRatios` (text-to-video shapes), `maxPromptChars` (prompt cap in characters, enforced with a 400) and `maxInputVideoSeconds` (longest `video_url` clip) on video and video-edit models; `maxPromptChars` (the `input` cap: 600 on Spicy Voice 1, 5,000 on Spicy Voice 2 and 3) on speech models.'
inputs:
type: object
properties:
first_frame:
type: string
description: '`required`, `optional` (text-to-video without it) or `none` for `image_url`.'
last_frame:
type: boolean
description: Whether `last_frame_url` is accepted (always together with a first frame or a continuation clip).
reference_images:
type: integer
description: Maximum `reference_image_urls` (a `character` counts as one); 0 when not supported.
reference_video:
type: boolean
description: Whether `video_url` is a reference clip to extend or edit (never with a first frame).
continuation_clip:
type: boolean
description: Whether `video_url` is a clip to continue, taking the place of the first frame.
audio:
type: object
description: '`mode`: `driving` (the clip is the soundtrack and the mouth follows it), `reference` (the model generates sound and uses the clip for voice, tone and beat) or `none`; `max_clips`; `max_total_seconds` where capped; `with_first_frame`, whether audio may be sent alongside `image_url`.'
aspect_ratio:
type: boolean
description: Whether `aspect_ratio` is accepted (text-to-video only).
smart_duration:
type: boolean
description: 'Whether `duration: -1` is accepted.'
combinations:
type: array
items:
type: string
description: The valid input combinations, one sentence each. Quoted back in any 400 for an invalid mix.
required:
- first_frame
- last_frame
- reference_images
- reference_video
- continuation_clip
- audio
- aspect_ratio
- smart_duration
- combinations
description: 'Video models only: what the model takes and which inputs may travel together. The route enforces exactly this.'
speech:
type: object
properties:
voices:
type: array
items:
type: string
description: Preset voice names; empty on `spicy-voice-1-custom`, which speaks your own voices.
custom_voices:
type: boolean
description: True when the model speaks your designed and cloned voices (`vc_...`).
instructions:
type: boolean
description: Whether `instructions` are accepted.
languages:
type: array
items:
type: string
description: Accepted `language` values, `Auto` first.
output_format:
type: string
description: The default format, `wav`. Spicy Voice 2 and 3 models also return `mp3`.
streaming:
type: boolean
description: 'Whether `stream: true` is accepted (Spicy Voice 2 and 3 models).'
stream_formats:
type: array
items:
type: string
description: 'Streaming models only: `pcm`, `wav`, `mp3`.'
tags:
type: object
description: 'Spicy Voice 2 and 3 models: `{ control, sounds }`, the inline tags the model performs inside `input` (on Spicy Voice 3 any short direction in brackets works too).'
voice_creation_usd:
type: object
description: '`spicy-voice-1-custom` only: `{ designed, cloned }`, the one-off fee per voice.'
required:
- voices
- custom_voices
- instructions
- languages
- output_format
- streaming
description: 'Speech models only: voices, options and output.'
video_edit:
type: object
properties:
mode:
type: string
description: '`instruction` (edit a clip from a prompt and reference images) or `motion` (the person in `image_url` performs the clip''s moves).'
min_clip_seconds:
type: integer
description: Shortest input clip accepted.
max_clip_seconds:
type: integer
description: Longest input clip accepted.
max_output_seconds:
type: integer
description: The output is the clip's length, capped here.
reference_images:
type: integer
description: Maximum `reference_image_urls`; 0 on motion transfer.
aspect_ratio:
type: boolean
description: Whether `aspect_ratio` can reshape the output.
keep_audio:
type: boolean
description: 'Whether `keep_audio: true` keeps the clip''s soundtrack.'
bills_input_seconds:
type: boolean
description: True when the input clip's seconds are billed as well as the output's.
qualities:
type: array
items:
type: string
description: 'Motion transfer only: `standard`, `pro`, priced separately.'
required:
- mode
- min_clip_seconds
- max_clip_seconds
- max_output_seconds
- reference_images
- aspect_ratio
- keep_audio
- bills_input_seconds
description: '`POST /v1/videos/edits` models only: how the model uses its clip.'
bills_input_video_seconds:
type: boolean
description: Present and true on video models that also bill the seconds of an input `video_url` clip at the same per-second rate (`spicy-motion-3`, `spicy-motion-3-fast`).
actions:
type: boolean
description: Present and true on video models that take `action` on `POST /v1/videos/generations` (`spicy-motion-3`, `spicy-motion-3-fast`); the library is `GET /v1/videos/actions`.
image_actions:
type: boolean
description: Present and true on image models that only run with `action` on `POST /v1/images/generations` (`spicy-image-action-1`); the library is `GET /v1/images/actions`.
upscale:
type: object
description: 'Upscaling models only (`spicy-upscale-1`): `scales` ([2, 4]), `usd_4x` (the 4x price; 2x is `pricing.usd`) and `max_pixels_4x` (the largest input 4x takes).'
silent:
type: boolean
description: Present and true on video models that always render without sound (`spicy-motion-draft-1`).
realtime:
type: object
properties:
voices:
type: array
items:
type: string
description: Voices accepted as `voice` on `POST /v1/realtime/sessions`.
default_voice:
type: string
description: Used when `voice` is omitted.
max_seconds:
type: integer
description: Longest call on one session.
input_audio:
type: string
description: 'What to send: PCM16 mono 16 kHz, base64.'
output_audio:
type: string
description: 'What comes back: PCM16 mono 24 kHz, base64.'
required:
- voices
- default_voice
- max_seconds
- input_audio
- output_audio
description: Live-call models only.
examples:
type: array
items:
type: string
description: Example output URLs for this model. For sandbox keys and accounts still owing their regional age check, stills come blurred and clips are left out, and the list carries `restricted` and `note`.
required:
- id
- kind
- label
- description
- featured
- requires_image
- accepts_image
- pricing
- accepts_reference
description: Every model available to you.
restricted:
type: string
description: 'Only on the locked shape: `explicit_media`.'
note:
type: string
description: 'Only on the locked shape: why, and how to get the full library.'
required:
- data
example:
data:
- id: spicy-motion-3
kind: video
label: Spicy Motion 3
featured: false
requires_image: false
accepts_image: true
accepts_reference: true
pricing:
unit: second
usd_by_resolution:
480P: 0.1
720P: 0.2
1080P: 0.4
limits:
resolutions:
- 480P
- 720P
- 1080P
minDuration: 2
maxDuration: 30
aspectRatios:
- '16:9'
- '9:16'
- '1:1'
- '4:3'
- '3:4'
- '21:9'
maxPromptChars: 20000
inputs:
first_frame: optional
last_frame: true
reference_images: 10
reference_video: true
continuation_clip: false
audio:
mode: reference
max_clips: 5
max_total_seconds: 15
with_first_frame: false
aspect_ratio: true
smart_duration: true
combinations:
- Text prompt only, with aspect_ratio; dialogue written in the prompt is spoken natively
- First frame (image_url), optionally a last frame (last_frame_url); no references or audio in the same request
- 'Reference images (up to 10, or a character) plus a text prompt: same person, framing chosen by the model'
- Reference images, a reference video (video_url, 15s max) and reference audio (up to 5 clips, 15s total) in any mix, with a text prompt; audio guides voice, tone and beat while the words come from the prompt
bills_input_video_seconds: true
actions: true
- id: spicy-image-1
kind: image
label: Spicy Image 1
featured: false
requires_image: false
accepts_image: false
accepts_reference: false
pricing:
unit: image
usd: 0.06
limits:
sizes:
- 1024*1024
- 832*1216
- 1216*832
- 1280*1280
- 1440*1440
- 1024*1536
- 1536*1024
- 1080*1920
- 1920*1080
- 1152*2048
- 2048*1152
maxOutputs: 6
- id: spicy-voice-1-custom
kind: speech
label: Spicy Voice 1 Custom
featured: false
requires_image: false
accepts_image: false
accepts_reference: false
pricing:
unit: 10K characters
usd_per_10k_chars: 0.3
limits:
maxPromptChars: 600
speech:
voices: []
custom_voices: true
instructions: false
languages:
- Auto
- English
- Chinese
- German
- Italian
- Portuguese
- Spanish
- Japanese
- Korean
- French
- Russian
output_format: wav
streaming: false
voice_creation_usd:
designed: 0.4
cloned: 0.02
'400':
description: 'Invalid parameters. Body: {error: {message, type: ''invalid_request_error''}}.'
'401':
description: Missing or invalid API key.
'402':
description: Insufficient balance. Top up in the dashboard or through the get_topup_link tool; nothing was charged.
'422':
description: Prompt blocked by moderation (acceptable use policy). Never charged.
'429':
description: Rate limited or model at capacity; retry after the Retry-After header.
/v1/account:
get:
operationId: getAccount
summary: Get Account
description: Read your balance and account status.
tags:
- Core
security:
- apiKey: []
responses:
'200':
description: Successful Response
content:
application/json:
schema:
type: object
properties:
email:
type: string
description: The account this key belongs to.
balance_usd:
type: number
description: Remaining balance in US dollars.
limits:
type: object
description: 'This account''s limits: `requests_per_minute` (600 to start, raised automatically up to 6,000 for accounts that keep reaching it, or on request), `declined_prompts_per_minute`, `screened_requests_per_end_user_per_minute` and `video_jobs_in_progress` (20 by default). Higher limits are available on request: contact@spicyapi.com.'
character_import:
type: object
description: 'Only on accounts that had a character import window: `status` (`open`, `expired`, `exhausted`, `revoked` or `not_enabled`), `expires_at`, `used`, `limit` and `remaining`. See `POST /v1/characters/import`.'
required:
- email
- balance_usd
- limits
example:
email: you@example.com
balance_usd: 42.75
sandbox: false
limits:
requests_per_minute: 600
declined_prompts_per_minute: 60
screened_requests_per_end_user_per_minute: 30
video_jobs_in_progress: 20
'400':
description: 'Invalid parameters. Body: {error: {message, type: ''invalid_request_error''}}.'
'401':
description: Missing or invalid API key.
'402':
description: Insufficient balance. Top up in the dashboard or through the get_topup_link tool; nothing was charged.
'422':
description: Prompt blocked by moderation (acceptable use policy). Never charged.
'429':
description: Rate limited or model at capacity; retry after the Retry-After header.
/v1/end-users/{user}:
delete:
operationId: eraseEndUser
summary: Erase an End User
description: 'Erase what was generated for one of your users, for their privacy requests. Pass the same `user` id you sent on their requests (URL-encoded). Erased: the request records sent with that id (prompt, parameters, inputs and output links removed; the charge, model and date stay for your invoices) and the images, clips and audio those requests produced, from the CDN and from your library. Kept: content screening records (declines, strikes), which abuse prevention and the law require us to keep. If the end user has any decline or strike on record, nothing is erased and the response is `held_for_review`: email contact@spicyapi.com with the id and we will review it. Requests sent without `user` cannot be tied to a person, so send it on every request if your users can ask for erasure.'
tags:
- Core
security:
- apiKey: []
responses:
'200':
description: Successful Response
content:
application/json:
schema:
type: object
properties:
status:
type: string
description: '`erased` or `held_for_review`.'
requests:
type: integer
description: Request records erased.
files:
type: integer
description: Generated files deleted.
reason:
type: string
description: 'With `held_for_review`: why, and what to do.'
required:
- status
example:
object: end_user.erasure
user: user_8f3a2c
status: erased
requests: 42
files: 37
'400':
description: 'Invalid parameters. Body: {error: {message, type: ''invalid_request_error''}}.'
'401':
description: Missing or invalid API key.
'402':
description: Insufficient balance. Top up in the dashboard or through the get_topup_link tool; nothing was charged.
'422':
description: Prompt blocked by moderation (acceptable use policy). Never charged.
'429':
description: Rate limited or model at capacity; retry after the Retry-After header.
components:
securitySchemes:
apiKey:
type: http
scheme: bearer
bearerFormat: sk-spicy-...
description: Per-account API key from https://www.spicyapi.com/dashboard/api-keys (shown once, stored hashed). Sandbox keys bill nothing.
x-openai-compatible:
baseUrl: https://api.spicyapi.com/v1
compatible:
- /v1/chat/completions
- /v1/images/generations
- /v1/models
- /v1/embeddings
- /v1/audio/transcriptions
notes: Image sizes use width*height (1024*1024). Speech returns JSON with a url unless stream is true. Live calls follow the OpenAI Realtime event shape over wss://api.spicyapi.com/v1/realtime after POST /v1/realtime/sessions. Edits and video are Spicy API specific.
x-mcp:
endpoint: https://www.spicyapi.com/api/mcp
transport: streamable-http
auth: 'Authorization: Bearer sk-spicy-...'
docs: https://www.spicyapi.com/docs
llms: https://www.spicyapi.com/llms.txt
skills: https://www.spicyapi.com/skills/index.json