OpenAI-compatible NSFW API
Spicy API speaks the OpenAI wire format for image generation and chat, so the official OpenAI SDKs work once you change the base URL and the key. The difference is the content policy: explicit content between consenting adults is allowed, where OpenAI, Anthropic and Google refuse it. Images from $0.02, chat from $0.1 per 1M prompt tokens, video from $0.05 per second, billed per generation with no subscription.
The two-line change
from openai import OpenAI
client = OpenAI(api_key="sk-spicy-...", base_url="https://api.spicyapi.com/v1")
# Images: the OpenAI SDK's images.generate maps onto POST /v1/images/generations
img = client.images.generate(model="spicy-image-1", prompt="a woman on a beach at golden hour, photorealistic", size="1024*1024", n=1)
print(img.data[0].url) # durable CDN URL, reusable as image_url for edits and video
# Chat: fully compatible, streaming included
stream = client.chat.completions.create(model="spicy-chat-1", messages=[{"role": "user", "content": "hey"}], stream=True)import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://api.spicyapi.com/v1", apiKey: process.env.SPICYAPI_KEY });
const img = await client.images.generate({ model: "spicy-image-1", prompt: "..." });
console.log(img.data[0].url);No OpenAI account or OpenAI key is involved; requests go only to https://api.spicyapi.com.
What is compatible and what is not
| OpenAI SDK call | Spicy API endpoint | Status |
|---|---|---|
client.images.generate | POST /v1/images/generations | Drop-in. n 1 to 6, size written with an asterisk ("1024*1024", the allowed sizes are on each model), returns data[].url plus cost_usd. URLs only, no b64_json. |
client.chat.completions.create | POST /v1/chat/completions | Drop-in, including stream=True. Text only: max_tokens up to 8192, n up to 4, response_format text or json_object; tools on spicy-chat-1 and spicy-companion-1; thinking, search and json_schema return 400. |
client.models.list | GET /v1/models | Drop-in, with prices and limits added to each model. |
client.images.edit | POST /v1/images/edits | JSON body with image_urls rather than a file upload: inputs must be images this account generated. Call it over HTTP. |
| (none) | POST /v1/videos/generations | Not an OpenAI endpoint. Two plain HTTP calls: start a task, poll GET /v1/videos/tasks/{id}. |
client.audio.speech.create | POST /v1/audio/speech | Same request fields (model, input, voice, instructions, response_format). Without stream the response is JSON with a url, not audio bytes; with stream: true on Spicy Voice 2 the body is the audio. Voices are the ones in GET /v1/voices. |
client.audio.transcriptions.create | POST /v1/audio/transcriptions | Drop-in with model="spicy-transcribe-1": multipart file, returns text plus language, duration_s and cost_usd. |
client.embeddings.create | POST /v1/embeddings | Drop-in with spicy-embed-1 (dimensions, encoding_format); spicy-embed-vision-1 also takes {"image": url} items from your own library. |
| Realtime API | POST /v1/realtime/sessions + WebSocket | Same event shape. Create the session over HTTP, then connect to the returned url; only session.turn_detection can change mid-call. |
| (none) | POST /v1/audio | Uploads a 2 to 30 second WAV or MP3 for lip-sync video (audio_url). |
| Assistants, files | (none) | Not offered. |
Models you can name in the SDK
| Model | Kind | Price |
|---|---|---|
spicy-image-1 | image | $0.06 per image |
spicy-image-1-pro | image | $0.09 per image |
spicy-image-photo-1 | image | $0.08 per image |
spicy-image-reference-1 | image | $0.12 per image |
spicy-image-action-1 | image | $0.15 per image |
spicy-chat-1 | chat | $0.8 per 1M prompt tokens ($0.16 when served from cache) and $2.4 per 1M completion tokens (minimum $0.001 per request) |
spicy-companion-1 | chat | $1 per 1M prompt tokens ($0.2 when served from cache) and $2.8 per 1M completion tokens (minimum $0.001 per request) |
spicy-companion-1-flash | chat | $0.1 per 1M prompt tokens ($0.02 when served from cache) and $0.8 per 1M completion tokens (minimum $0.0005 per request) |
spicy-transcribe-1 | transcription | $0.0042 per minute of audio, billed by the second (minimum $0.0001 per request) |
spicy-embed-1 | embedding | $0.14 per 1M tokens |
spicy-embed-vision-1 | embedding | $0.18 per 1M text tokens and $0.06 per 1M image tokens |
Video and edit models: /pricing.
Video from the same key
curl https://api.spicyapi.com/v1/videos/generations \
-H "Authorization: Bearer $SPICYAPI_KEY" -H "Content-Type: application/json" \
-d '{"model": "spicy-motion-2", "prompt": "slow build, steady rhythm", "image_url": "<a URL from /v1/images/generations>", "resolution": "720P", "duration": 5}'
# 202 {"id": "sj_...", "status": "queued", "cost_usd": 1.00} then poll every 10 to 15 seconds:
curl https://api.spicyapi.com/v1/videos/tasks/sj_... -H "Authorization: Bearer $SPICYAPI_KEY"Errors look like OpenAI's
{"error": {"message": "...", "type": "insufficient_balance"}} with 401 bad key, 402 balance, 400 invalid parameters, 422 prompt blocked by moderation (never charged; if wrong, POST error.moderation_id to /v1/moderations/appeals), 429 rate limited or model at capacity (honour Retry-After). SDK retry and error classes behave as they do against OpenAI.
What "uncensored" does not mean
Minors in any form, real people (with or without consent), non-consensual scenes in images and video and the rest of the prohibited list are blocked at the prompt, before any charge: /acceptable-use. Your product must age-gate its users under the law of each user's country; where that law requires checks, a self-declared age is not enough.
Start
Sign in at /auth, take the Default key, try a sandbox key for free fixture responses, then top up from $50. Full guide: /docs. Letting a coding agent wire it up: /docs/mcp.
For AI agents
Machine-readable overview: /llms.txt. OpenAPI: /openapi.json. MCP endpoint: /api/mcp (Claude Code: claude mcp add --transport http spicyapi https://www.spicyapi.com/api/mcp --header "Authorization: Bearer sk-spicy-..."; OAuth clients need only the URL; guide: /docs/mcp). Skills: /skills/index.json. A sandbox key answers everything from fixtures with nothing billed.