AI API for Developers

The DeepFA AI API,
OpenAI-compatible

GPT, Claude, Gemini, Grok and DeepSeek behind one address and one key. Because the API is exactly the OpenAI standard, the libraries and tools you already have — the official Python and JavaScript clients, VS Code extensions, Cursor — connect to DeepFA by changing one base URL, and run on rial credit.

5 vendors
Behind one address
OpenAI
Standard compatible
Rial
No foreign card
⚡ OpenAI compatible

Change one URL and it works everywhere

OpenAI-compatible means the request and response shape of our API is exactly the OpenAI standard — not that we only serve OpenAI models. So anything built for OpenAI — your own code, a server, a mobile app, an automation, the VS Code extensions, Cursor — connects by changing one base URL and runs GPT, Claude, Gemini, Grok and DeepSeek on a rial-denominated balance.

Base URL
https://deepfa.ir/api/v1
cURL
curl https://deepfa.ir/api/v1/chat/completions \
  -H "Authorization: Bearer $DEEPFA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-6-luna",
    "messages": [{"role": "user", "content": "سلام"}]
  }'
Python
from openai import OpenAI

client = OpenAI(
    api_key="YOUR_DEEPFA_KEY",
    base_url="https://deepfa.ir/api/v1",
)

answer = client.chat.completions.create(
    model="claude-sonnet-5",
    messages=[{"role": "user", "content": "سلام"}],
)

print(answer.choices[0].message.content)
Node.js
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "YOUR_DEEPFA_KEY",
  baseURL: "https://deepfa.ir/api/v1",
});

const answer = await client.chat.completions.create({
  model: "gemini-3.8-flash",
  messages: [{ role: "user", content: "سلام" }],
});

The endpoints

All under the base URL
POST /chat/completions Chat, with streaming and tool calling
POST /responses OpenAI's Responses API, for Codex and OpenAI models
POST /messages Anthropic's Messages API, for Claude Code and Claude models
POST /messages/count_tokens Count a Claude request's tokens, free
GET /models The models your key may call
GET /balance Balance and this key's ceilings
POST /embeddings Text to vectors, for search
POST /images/generations Image generation
POST /images/edits Image to image
POST /audio/transcriptions Speech to text
POST /audio/speech Text to speech
POST /videos Video from text, an image or a video
GET /videos/{id} How a video is getting on
GET /videos/{id}/content The finished video
POST /music A song with lyrics and vocals, or instrumental
GET /music/{id} How a song is getting on, and its lyrics
GET /music/{id}/content The finished song
POST /podcasts A one- or two-voice podcast from a script
GET /podcasts/{id} How a podcast is getting on, and its transcript
GET /podcasts/{id}/content The finished podcast
POST /agents/runs Start an agent: research, analysis or a site
GET /agents/runs/{id} A run: its status and files

Every endpoint spends the same API credit: chat and embeddings by the tokens they use, images per image, video by length and resolution, music per request, transcription per minute and speech per character. What each call cost is returned in a response header and listed on your usage page.

The agents, from your own code

An agent takes a job from end to end: it searches the web, writes and runs code in a sandbox, and hands back an answer with the files it produced - a report, a chart, a spreadsheet or a finished web page. All three agents of the panel run from your own code with the same key.

1 Start

One POST to /agents/runs with the agent and its input; you get a run id.

2 Poll

GET /agents/runs/{id} every few seconds; the status moves from processing to completed.

3 Collect

The answer and a list of files; each one has a URL you download with the same key.

POST /api/v1/agents/runs
curl https://deepfa.ir/api/v1/agents/runs \
  -H "Authorization: Bearer $DEEPFA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"agent":"research","input":{"topic":"...","depth":"standard","language":"fa"}}'

A run is charged when it finishes, from your API credit: the model it used, each web search and the sandbox session. A run that fails, is cancelled or produces nothing is not charged.

What each model costs

Per million tokens. The same work can cost twenty times more on one model than another, so it is worth reading before you choose one.

%
Below the makers' own prices
Most models in this table cost less than their maker's own list price. The "Against the list price" column shows each model's saving.
Model Maker's list price Against the list price Input Cached input Output 1M in + 1M out
OpenAI
text-embedding-3-small openai 0.02 USD — 50 — 0 0.0286 USD
text-embedding-3-large openai 0.13 USD — 325 — 0 0.19 USD
gpt-6-luna openai 0.60 USD up to 57% less at least 17% in every plan 75 7.5 375 0.26 USD
gpt-6.1-terra openai 6.00 USD up to 57% less at least 17% in every plan 750 37.5 3,750 2.57 USD
gpt-6.1-sol openai 12.00 USD up to 57% less at least 17% in every plan 1,500 75 7,500 5.14 USD
gpt-5.3-codex openai 15.75 USD up to 43% less 1,750 175 14,000 9.00 USD
gpt-6-astra openai 60.00 USD up to 60% less at least 23% in every plan 7,000 700 35,000 24.00 USD
Anthropic (Claude)
claude-haiku-5-5 anthropic 0.60 USD up to 14% less 150 15 750 0.51 USD
claude-sonnet-5-5 anthropic 12.00 USD up to 43% less 2,000 200 10,000 6.86 USD
claude-sonnet-5 anthropic 12.00 USD up to 39% less 2,125 212.5 10,687.5 7.32 USD
claude-opus-5-5 anthropic 24.00 USD up to 43% less 4,000 200 20,000 13.72 USD
claude-opus-5 anthropic 30.00 USD up to 43% less 5,000 500 25,000 17.15 USD
claude-fable-5 anthropic 60.00 USD up to 43% less 10,000 1,000 50,000 34.29 USD
claude-fable-5-1 anthropic 60.00 USD — 25,000 625 125,000 85.73 USD
Google (Gemini)
gemini-3.7-flash google 4.50 USD up to 57% less at least 17% in every plan 562.5 56.25 2,812.5 1.93 USD
gemini-3.8-flash google 9.00 USD up to 79% less at least 59% in every plan 562.5 56.25 2,812.5 1.93 USD
gemini-3.1-pro-preview google 14.00 USD up to 59% less at least 21% in every plan 1,250 125 8,750 5.72 USD
gemini-4-argon google 12.00 USD up to 43% less 2,000 200 10,000 6.86 USD
xAI (Grok)
grok-4.3 xai 3.75 USD up to 43% less 1,250 200 2,500 2.14 USD
grok-4.6 xai 8.00 USD up to 43% less 2,000 500 6,000 4.57 USD
grok-4.7 xai 8.00 USD up to 43% less 2,000 500 6,000 4.57 USD
DeepSeek
deepseek-flash deepseek 1.50 USD up to 43% less 300 6 1,187.5 0.85 USD
deepseek-v4-pro deepseek 5.28 USD — 3,250 108.25 9,875 7.50 USD
Perplexity
sonar perplexity 2.00 USD — 2,500 — 2,500 2.86 USD
sonar-reasoning-pro perplexity 10.00 USD — 5,000 — 20,000 14.29 USD

The input and output columns are credits per million tokens. The money column is the same amount at the lowest price per credit (the largest API pack). "Up to" is the saving at the cheapest credit (the largest API pack, as in the money columns); "at least … in every plan" is the saving at the dearest credit any plan or pack sells. The list price is a million input plus a million output tokens on the maker's own site.

Model Maker's list price Against the list price Unit Credits USD
Images
gpt-image-2.5-sunburst Images 0.22 USD up to 80% less at least 62% in every plan per image 75 0.0429
gpt-image-2.5-flare Images 0.22 USD up to 80% less at least 62% in every plan per image 75 0.0429
gpt-image-1 Images 0.17 USD — per image 625 0.36
flux-3 Images 0.048 USD — per image 125 0.0714
flux-3-klein Images 0.009 USD — per image 25 0.0143
flux-schnell Images 0.003 USD — per image 25 0.0143
nano-banana-2.1 Images 0.0336 USD up to 15% less per image 50 0.0286
nano-banana-2-lite Images 0.0336 USD up to 15% less per image 50 0.0286
Text to speech
tts-1 Text to speech — — per 1,000 characters 37.5 0.0214
tts-1-hd Text to speech — — per 1,000 characters 75 0.0429
gpt-4o-mini-tts Text to speech — — per 1,000 characters 37.5 0.0214
eleven-v4 Text to speech — — per 1,000 characters 200 0.11
eleven-v4-turbo Text to speech — — per 1,000 characters 100.1 0.0572
gemini-3.8-flash-lite-tts Text to speech 0.0153 USD up to 2% less per 1,000 characters 26.3 0.015
Transcription
gpt-transcribe Transcription — — per minute 11.25 0.0064
whisper-1 Transcription — — per minute 15 0.0086
gpt-4o-transcribe Transcription — — per minute 15 0.0086
gpt-4o-mini-transcribe Transcription — — per minute 7.5 0.0043
Video
kling-3-turbo-pro Video 0.70 USD — per 5-second clip 1,425 0.81
luma-ray-32 Video 0.50 USD — per 5-second clip, 540p 1,250 0.71
grok-imagine-15 Video 0.24 USD up to 76% less at least 54% in every plan per 3-second clip, 480p 100 0.0571
minimax-h3-max Video 0.40 USD up to 29% less per 5-second clip, 768p 500 0.29
wan-30 Video 0.25 USD — per 5-second clip, 480p 500 0.29
kling-3-pro Video 0.84 USD — per 5-second clip 1,700 0.97
kling-o3 Video 0.70 USD — per 5-second clip 1,750 1.00
google-veo-31 Video 3.20 USD up to 44% less per 8-second clip, 720p 3,125 1.79
google-veo-31-fast Video 1.20 USD up to 64% less at least 31% in every plan per 8-second clip, 720p 750 0.43
google-veo-31-lite Video 0.40 USD up to 46% less per 8-second clip, 720p 375 0.21
seedance-25 Video 1.10 USD up to 8% less per 5-second clip, 480p 1,775 1.01
kling-4 Video 0.47 USD — per 3-second clip, 720p 1,075 0.61
kling-video-pro Video 0.84 USD — per 5-second clip 1,700 0.97
kling-video-o3 Video 0.70 USD — per 5-second clip 1,750 1.00
luma-dream-machine Video 0.15 USD — per 5-second clip, 540p 375 0.21
wan-video-25 Video 0.25 USD — per 5-second clip, 480p 625 0.36
bytedance-upscaler Video 0.0072 USD — per second of video, 1080p 20 0.0114
happy-horse-edit Video 0.28 USD up to 29% less per second of video, 720p 350 0.20
kling-o3-pro-edit Video 0.17 USD — per second of video 420 0.24
grok-imagine-edit Video 0.06 USD — per second of video, 480p 150 0.0857
Music
suno-v6 Music — — per request, 2 songs 150 0.0857
lyria-3.5 Music — — per song 250 0.14
minimax-music-2.5 Music — — per song 375 0.21

Images, video, speech and transcription spend the same API credit, and the dollar column is at the lowest price per credit (the largest API pack).

In your editor

VS Code — Continue
{
  "models": [{
    "title": "DeepFA",
    "provider": "openai",
    "model": "claude-sonnet-5",
    "apiKey": "YOUR_DEEPFA_KEY",
    "apiBase": "https://deepfa.ir/api/v1"
  }]
}
VS Code — GitHub Copilot
"github.copilot.chat.customOAIModels": [{
  "modelId": "claude-sonnet-5",
  "displayName": "DeepFA Claude Sonnet 5",
  "endpoint": "https://deepfa.ir/api/v1",
  "apiKey": "YOUR_DEEPFA_KEY"
}]
Cursor
# Settings → Models → OpenAI API

Base URL:  https://deepfa.ir/api/v1
API Key:   YOUR_DEEPFA_KEY
Model:     gpt-6.1-sol  /  claude-sonnet-5-5
Cline / Roo Code / Kilo Code
Provider:  OpenAI Compatible

Base URL:  https://deepfa.ir/api/v1
API Key:   YOUR_DEEPFA_KEY
Model ID:  claude-sonnet-5
Claude Code
// ~/.claude/settings.json
{
  "env": {
    "ANTHROPIC_BASE_URL": "https://deepfa.ir/api",
    "ANTHROPIC_AUTH_TOKEN": "YOUR_DEEPFA_KEY",
    "ANTHROPIC_MODEL": "claude-sonnet-5-5"
  }
}
Codex
# ~/.codex/config.toml
model = "gpt-6.1-sol"
model_provider = "deepfa"

[model_providers.deepfa]
name = "DeepFA"
base_url = "https://deepfa.ir/api/v1"
env_key = "DEEPFA_API_KEY"
wire_api = "responses"
Get an API key

You create and revoke keys from your own dashboard. Each key can be held to a daily and a monthly credit ceiling, to IP addresses, endpoints and models, and to an end date, or switched off for a while.

An OpenAI-compatible gateway, for developers and businesses

The DeepFA AI API is a gateway that speaks the OpenAI standard: the same /v1/chat/completions path, the same request body, the same response shape and the same error format. Any library, extension or service that works with OpenAI today connects to DeepFA by changing the base URL and the key — no rewrite, no bespoke SDK, no new contract to learn. Behind that one address sit GPT, Claude, Gemini, Grok and DeepSeek models, and switching between them means changing one string in the model field. Claude Code and Codex, which speak other shapes, connect with the same key through /v1/messages and /v1/responses.

Beyond chat, the same address serves embeddings for semantic search and RAG, image generation with GPT Image, FLUX and Nano Banana, video generation, speech-to-text and text-to-speech. SSE streaming, tool calling, structured output and image input are all supported and behave exactly as they do upstream. The cost of every call comes back in a response header and is recorded on the API page of your dashboard, broken down by key and by model — failed requests included, so your credit is never a black hole.

For a developer in Iran the difference that matters most is payment: credit is bought in rial through a local gateway, no international card is needed, and bought credit never expires. Each key can carry a daily and monthly credit ceiling, a per-minute request limit, allow-lists of models and endpoints, allowed IP addresses and an end date, or be switched off for a while, so a key handed to a script or a colleague cannot empty the account — and can be revoked in one click if it leaks. You are emailed before your API credit runs out.

Key Features

Why the DeepFA AI API?

Built with developer needs in focus — easy to start, secure to use and scalable for growth.

⚡

OpenAI-compatible

The same paths, the same request body, the same response shape. The official OpenAI libraries and anything built on them connect to DeepFA by changing one base URL, and Claude Code and Codex through routes of their own.

🔀

One key, every vendor

GPT, Claude, Gemini, Grok and DeepSeek behind one key and one address. Switching model means changing one string, not changing libraries, accounts and invoices.

🌊

Streaming, tools and vision

Token-by-token SSE streaming, tool calling, structured output and image input — none of it needing a change to code you have already written.

🛡️

A spending ceiling per key

Set a daily and monthly ceiling, a per-minute request limit, the models and endpoints allowed, IP addresses and an end date on each key. A key you hand to a script cannot empty the account.

📊

What every call cost

The cost of each request comes back in a response header and is recorded on your usage page by key and by model — failures included. Your credit is not a black hole.

💳

Pay in rial, no foreign card

Buy credit through a local gateway, and bought credit never expires. No international card, nothing to work around.

📦

Thousands of requests in one file

With the Batch API, send thousands of headlines, summaries or translations in one JSONL file; they run in the background within a day and the answers come back as one file. No rate limit to pace, no retries to write: the same shape as OpenAI's Batch API.

🔔

Told when a job ends, by webhook

Instead of asking again and again whether a video, a song, a podcast, an agent run or a batch is ready, give an https address and a signed event is posted to it when each one ends (the Standard Webhooks spec OpenAI uses).

🏷️

Usage labels and team credit

With the X-DeepFA-Tag header, put each request down to a project, a department or a customer and see the spending that way. A team owner can open the API to members, whose keys then spend the team's credit within each member's monthly limit.

API Endpoints

The endpoints you can call

All under one base URL, all with the same key, all in the request and response shape you know from OpenAI — and /messages in Anthropic's.

🔒 Every endpoint wants your API key in the Authorization header — exactly as you send it to OpenAI
API reference

What each endpoint takes and returns

Everything beyond the standard OpenAI shape: chat features, image and audio parameters, video jobs, the model list, the balance, and every error and limit.

Function calling (tools)

Send tools in the OpenAI shape. When the model wants one, the answer carries tool_calls instead of text; run the function yourself and send the result back with the tool role and the same tool_call_id, and the model writes its final answer. Works with every text model except Sonar, which searches the web by itself and takes no tools.

{
  "model": "gpt-6-luna",
  "messages": [{"role": "user", "content": "What is the weather in Tehran?"}],
  "tools": [{
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "Current weather for a city",
      "parameters": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"]
      }
    }
  }],
  "tool_choice": "auto"
}
{"role": "tool", "tool_call_id": "call_8f2...", "content": "{\"temp_c\": 21}"}

JSON output (response_format)

With {"type": "json_object"} the answer is valid JSON; with json_schema it comes back in exactly the structure you define.

{
  "model": "gpt-6-luna",
  "messages": [{"role": "user", "content": "Three colours, as JSON."}],
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "colours",
      "schema": {
        "type": "object",
        "properties": {"colours": {"type": "array", "items": {"type": "string"}}},
        "required": ["colours"]
      }
    }
  }
}

Image input and reasoning effort

To send a picture, make content an array with an image_url: a public https address, or a base64 data URL (data:image/png;base64,…). Reasoning models (GPT-5, GPT-6, the o-series and Gemini) take reasoning_effort as low, medium or high; left out, the model's own default applies (medium on GPT-6). GPT-6 and the o-series do not accept temperature or top_p.

{
  "model": "gpt-6-luna",
  "reasoning_effort": "low",
  "messages": [{
    "role": "user",
    "content": [
      {"type": "text", "text": "What is in this picture?"},
      {"type": "image_url", "image_url": {"url": "https://example.com/cat.png"}}
    ]
  }]
}

Prompt caching

The part of a prompt the model has already seen (a fixed system message, say) is charged at the "cached input" rate in the price table, and its count comes back in usage.prompt_tokens_details.cached_tokens. It is automatic on GPT, Gemini and DeepSeek; on Claude, put cache_control with type ephemeral on a message or on the whole request (on /v1/messages Claude Code's own markers go through as they are).

POST /v1/messages

Anthropic's Messages API shape, for Claude models; the route Claude Code calls with ANTHROPIC_BASE_URL set to https://deepfa.ir/api. The body goes through unchanged: block-form system, cache_control, thinking and tools, with the anthropic-beta and anthropic-version headers. A stream comes back event by event in order, and errors are in Anthropic's shape. Dated ids such as claude-haiku-4-5-20251001 and the [1m] suffix are accepted.

A few things are removed, because each costs more than the token rates in the price table: speed (fast mode), inference_geo and service_tier, and the server-side web search and code execution tools that Anthropic bills per use. POST /v1/messages/count_tokens counts a request's tokens free of charge. Models other than Claude are served by /v1/chat/completions.

POST /v1/responses

OpenAI's Responses API shape, for OpenAI models; the only shape Codex speaks (wire_api = "responses"). input items, reasoning items with their encrypted content, and function, custom and shell tools pass through unchanged. A stored response (the default, unless "store": false) is kept for thirty days, and its previous_response_id works for the same account only. The conversation parameter is not supported.

Removed: service_tier, background, and the hosted tools billed per use (web and file search, code interpreter, image generation, computer use and remote MCP).

Retired model names

A request naming a model that has been replaced, such as gpt-5.6-luna, is answered by its replacement (gpt-6-luna) at its price, and the key's owner is told once by email and in the dashboard. The names are listed on the Models tab of the API page.

POST /v1/images/generations — pictures come back as b64_json (base64 PNG), and only the pictures actually made are charged.

FieldDescription
modelDefault gpt-image-2.5-sunburst. Also gpt-image-2.5-flare, gpt-image-1, flux-3, flux-3-klein, flux-schnell, nano-banana-2.1 and nano-banana-2-lite.
promptRequired; what to draw.
nHow many, 1 to 10 (default 1).
sizeSuch as 1024x1024, 1536x1024 or 1024x1536. For FLUX, GPT Image 2.5 and Nano Banana it becomes the nearest aspect ratio the model makes.
quality, background, output_formatFor gpt-image-1, as OpenAI defines them.
{
  "model": "flux-schnell",
  "prompt": "A lighthouse at dawn, watercolour",
  "n": 2,
  "size": "1536x1024"
}

POST /v1/images/edits

Image to image, sent as multipart/form-data as with OpenAI: one to four pictures with a description, and the new picture comes back as b64_json. A picture costs the model's price; where the supplier bills every input picture, each one adds the credits_per_input_image shown by GET /v1/models.

FieldDescription
image / image[]Required; one to four PNG, JPEG or WebP pictures (up to three on nano-banana-2-lite), up to 10 MB each (made about one megapixel).
modelDefault gpt-image-2.5-sunburst. Also gpt-image-2.5-flare, nano-banana-2.1, nano-banana-2-lite, flux-3 and flux-3-klein.
promptRequired; what to make from the pictures.
nHow many, 1 to 10 (default 1).
sizeOptional; such as 1024x1024, or auto for the shape of the input picture.
curl https://deepfa.ir/api/v1/images/edits \
  -H "Authorization: Bearer $DEEPFA_API_KEY" \
  -F model=flux-3 \
  -F "image[]=@product.png" \
  -F "prompt=Place this bottle on a marble counter in soft morning light"

POST /v1/audio/speech

Returns the audio file itself, charged per character.

FieldDescription
modelDefault tts-1. Also tts-1-hd, gpt-4o-mini-tts, and eleven-v4 and eleven-v4-turbo (faster), which read Persian and more than ninety other languages. And gemini-3.8-flash-lite-tts, which reads Persian, English and other languages with seventy voices.
inputRequired; the text, at most 4,096 characters a request.
voiceFor the OpenAI models one of alloy, ash, ballad, coral, echo, fable, nova, onyx, sage, shimmer, verse (default alloy). For the eleven models the name of an ElevenLabs voice, such as Rachel.
response_formatmp3 (default), opus, aac, flac, wav, pcm — the eleven models always return mp3.
voice (Gemini)For gemini-3.8-flash-lite-tts, one of the seventy Gemini voices, such as Fola (default), Zephyr, Kore, Puck or Charon.
speedReading speed (optional).
instructionsTone and delivery, for gpt-4o-mini-tts and gemini-3.8-flash-lite-tts.
languageThe text's language, for the eleven models (optional).

POST /v1/audio/transcriptions

Sent as multipart/form-data; charged per started minute.

FieldDescription
fileRequired; an audio or video file, at most 25 MB.
modelDefault gpt-transcribe. Also gpt-4o-transcribe, gpt-4o-mini-transcribe and whisper-1 until OpenAI shuts them down on 2027-02-26; from then on their requests are served by gpt-transcribe.
languages[], keywords[], promptOptional with gpt-transcribe: the languages the audio may be in (e.g. fa), words you expect to hear, and a note on the topic. A single language is accepted too and sent as languages[].
language, temperatureOptional with the older models, as OpenAI defines them.
response_formatjson (default) or text; with whisper-1 (until 2027-02-26) also srt, vtt and verbose_json.

Making a video takes minutes, so it is a job: POST /v1/videos starts it and at once returns its id with the status queued; poll GET /v1/videos/{id} every few seconds until the status moves from in_progress to completed (with the file's url) or failed; GET /v1/videos/{id}/content redirects to the finished file (302), or answers 409 if it is not ready. The credit is charged when the job is accepted, and given back in full if it fails.

FieldDescription
modelRequired; from the table below.
promptRequired (except for bytedance-upscaler).
image_urlA public https address of a picture, to animate it.
video_urlA public https address of a video, to edit it. Do not send both image_url and video_url.
secondsThe clip's length, one of the model's lengths below (default 5). Not needed for an edit: the length is read from the source video itself, which must run 1 to 120 seconds.
resolutionSuch as 480p, 720p or 1080p. Left out, or not one the model makes, the model's default is used. The price changes with the resolution and length.
aspect_ratio16:9 (default), 9:16, or 1:1 on the models that make it.
audioSound, on the models that make it (default true).
fps, keep_audio, audio_settingEdits only: the frame rate for bytedance-upscaler (default 30), keeping the source video's sound (default true), and the sound setting on happy-horse-edit.

Models and the lengths they make

ModelJobSeconds
kling-3-turbo-pro text to video 5, 10
luma-ray-32 text to video 5, 10
grok-imagine-15 text to video, image to video (image_url) 3, 5, 10, 15
minimax-h3-max text to video 5, 10, 15
wan-30 text to video 5, 10, 15
kling-3-pro text to video 5, 10
kling-o3 text to video 5, 10
google-veo-31 text to video, image to video (image_url) 4, 6, 8
google-veo-31-fast text to video, image to video (image_url) 4, 6, 8
google-veo-31-lite text to video, image to video (image_url) 4, 6, 8
seedance-25 text to video, image to video (image_url) 5, 10, 15, 20, 30
kling-4 text to video, image to video (image_url) 3, 5, 10, 15, 20, 30
kling-video-pro image to video (image_url) 5, 10
kling-video-o3 image to video (image_url) 5, 10
luma-dream-machine image to video (image_url) 5
wan-video-25 image to video (image_url) 5, 10
bytedance-upscaler video edit (video_url) the source video's length
happy-horse-edit video edit (video_url) the source video's length
kling-o3-pro-edit video edit (video_url) the source video's length
grok-imagine-edit video edit (video_url) the source video's length
curl https://deepfa.ir/api/v1/videos \
  -H "Authorization: Bearer $DEEPFA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "grok-imagine-15",
  "prompt": "A paper boat sailing down a rainy street",
  "seconds": 5,
  "resolution": "720p",
  "aspect_ratio": "16:9"
}'
{
  "id": "t_48213",
  "object": "video",
  "model": "grok-imagine-15",
  "kind": "text_to_video",
  "status": "queued",
  "seconds": 5,
  "created_at": 1790443124
}

A podcast is a job, like a video: POST /v1/podcasts takes the script and returns an id such as p_123 at once; ask GET /v1/podcasts/{id} until its status is completed, then fetch the audio from GET /v1/podcasts/{id}/content (?what=transcript for the text, ?what=srt for subtitles). The voices are made by gemini-3.8-flash-lite-tts; you pay once, after the whole podcast exists, by the characters read and at the rate of /v1/audio/speech for this model - nothing is charged if it fails. The script is yours to bring (write it with /v1/chat/completions).

FieldDescription
turnsThe script as a list of {speaker: 1 to 4, text, style}. style is optional and in English, such as warmly or quietly amazed. Or send script instead.
scriptThe script as text with lines such as "Sara: hello". The names are the ones in names, or labels such as Speaker 1.
voices, namesUp to four voices and the names of the hosts (default Laomedeia, Alnilam, Sulafat and Puck). The voices are the Gemini ones. With more than two hosts the voices are recorded two at a time.
languageA language code such as fa, en, ar, tr … (default en).
kind, natural, titlekind solo means one speaker; natural adds the little fillers and pauses of real talk; title names the episode.
Sound tagsInside the text you can write <laugh>, <sigh>, <gasp>, <short pause> and <long pause>; the Persian words work too: <خنده>, <آه>, <مکث کوتاه>, <مکث بلند>.

At most 12,000 characters a podcast (about twenty minutes) and three podcasts at once per account. A podcast made through the API also appears in the AI Podcast tool.

curl https://deepfa.ir/api/v1/podcasts \
  -H "Authorization: Bearer $DEEPFA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"language":"en","voices":["Kore","Puck"],"turns":[{"speaker":1,"text":"Hi everyone, welcome! "},{"speaker":2,"text":"Glad to be here.","style":"warmly"}]}'
{"id":"p_123","object":"podcast","model":"gemini-3.8-flash-lite-tts","status":"queued","progress":0}

For thousands of requests, in the shape of OpenAI's Batch API and with the same libraries: write the requests in a JSONL file (one a line), upload it with POST /v1/files and purpose=batch, start it with POST /v1/batches, ask GET /v1/batches/{id} until its status is completed, and download the answers from GET /v1/files/{output_file_id}/content. The requests run in the background within 24 hours, without the key's rate limit, each charged exactly as the same live request would be and within the key's daily and monthly ceilings.

{"custom_id": "news-1", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-6-luna", "messages": [{"role": "user", "content": "..."}]}}
{"custom_id": "news-2", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-6-luna", "messages": [{"role": "user", "content": "..."}]}}
curl https://deepfa.ir/api/v1/files -H "Authorization: Bearer $DEEPFA_API_KEY" -F purpose=batch -F file=@requests.jsonl
curl https://deepfa.ir/api/v1/batches -H "Authorization: Bearer $DEEPFA_API_KEY" -H "Content-Type: application/json" \
  -d '{"input_file_id": "file-...", "endpoint": "/v1/chat/completions", "completion_window": "24h"}'
PointDescription
endpoint/v1/chat/completions or /v1/embeddings; every line of the file must name that url.
custom_idRequired and unique within the file; each answer comes back with it, since the order is not guaranteed.
File checkIf any line is invalid (bad JSON, an unknown model, a repeated custom_id), the batch comes back failed with the list in errors, and nothing is run.
Resultoutput_file_id holds the answers that succeeded and error_file_id the requests that did not; each line carries custom_id, response.status_code and response.body. request_counts, usage and credits sum up the work and its cost.
Cancel and expiryPOST /v1/batches/{id}/cancel drops what has not run, and what has run stays in the file. Whatever has not run within 24 hours appears in the error file as batch_expired, and costs nothing.
LimitsAt most 50,000 requests a batch; the file up to the server's upload limit (the error names it). Files are kept for thirty days and read only with a key of the same account.

Instead of asking again and again, give an https address on the Connect tab of the API page. When a long job ends an event is posted to it, and tried again for about a day until your server answers 2xx (after 1, 5 and 30 minutes, then 2, 6 and 15 hours). The body names the job only; fetch the result with your key.

{"id": "evt_...", "object": "event", "type": "video.completed", "created_at": 1793000000,
 "data": {"id": "t_123", "object": "video", "status": "completed"}}
EventWhen
video.completed, video.failedA video is done, or failed (the credit is given back).
music.completed, music.failedA song is done, or failed.
podcast.completed, podcast.failedA podcast is done, or failed.
agent_run.completed, agent_run.failed, agent_run.cancelledAn agent run ended.
batch.completed, batch.failed, batch.expired, batch.cancelledA batch ended.

Checking the signature

Each post carries the three Standard Webhooks headers OpenAI's own webhooks use: webhook-id, webhook-timestamp and webhook-signature (v1, followed by the base64 HMAC-SHA256 of "id.timestamp.body" under the signing secret's bytes). The signing secret (whsec_...) is on the same Connect tab; the Standard Webhooks libraries and webhooks.unwrap in OpenAI's official SDK verify it.

# pip install standardwebhooks
from standardwebhooks.webhooks import Webhook

event = Webhook("whsec_...").verify(request_body, request_headers)  # raises if forged

GET /v1/models

Lists only the models your plan and key allow, each with a pricing object in credits. Text models: input_per_million_tokens, output_per_million_tokens, and where they apply cached_input_per_million_tokens and cache_write_per_million_tokens. Other models: credits per credits_per (image, character, minute, video or second); for a video, seconds and resolution name the clip that price is for. Always the price actually charged.

GET /v1/balance

What this key can spend, at no charge. available is the account credit the API can draw on, and pockets splits it in the order it is spent: API credit, plan credit, prepaid credit. key shows this key's daily and monthly ceilings with what has gone against them, and spendable is what the key can spend right now: the balance narrowed by the nearest ceiling. On an unlimited account, unlimited is true and available is null. For a team member whose owner opened the API to them, pockets.team is their share of the team's credit (within their monthly limit), counted in available.

curl https://deepfa.ir/api/v1/balance -H "Authorization: Bearer $DEEPFA_API_KEY"
{
  "object": "balance",
  "unit": "credits",
  "unlimited": false,
  "available": 6500,
  "pockets": {"api": 5000, "plan": 1200, "prepaid": 300},
  "key": {
    "name": "production",
    "rpm_limit": 60,
    "daily":   {"limit": 100,  "spent": 30, "remaining": 70},
    "monthly": {"limit": null, "spent": 30, "remaining": null}
  },
  "spendable": 70
}

Every error comes back in the standard OpenAI shape, with code the same as type; param names the field at fault. On /v1/messages it comes back in Anthropic's shape instead.

{
  "error": {
    "message": "The model \"gpt-9\" is not available.",
    "type": "model_not_found",
    "param": "model",
    "code": "model_not_found"
  }
}
HTTPtypeMeaning
400invalid_request_errorA field is missing or wrong; param names it.
401invalid_api_keyThe key is wrong, revoked, or not sent at all (invalid_request_error).
401key_expiredThe end date you set on this key has passed.
403account_inactiveThe account is not verified or not active.
403key_disabledYou switched this key off on the API page.
403ip_not_allowedThe request came from an address that is not on the list allowed for this key.
403endpoint_not_allowedThis key is not allowed to call this endpoint.
403permission_deniedYour plan does not include this agent.
404model_not_foundThe model does not exist, or your plan or key does not allow it.
404not_foundNo video or run with that id.
404invalid_request_errorThe address is not an endpoint; the message points to this reference.
409invalid_request_errorThe video is not ready yet, or it failed (from the content path).
409idempotency_key_in_useA request with this Idempotency-Key is still running; send it again in a few seconds.
422idempotency_key_reusedThis Idempotency-Key was used for a different request; send a new key with a new request.
413invalid_request_errorThe file to transcribe is over 25 MB.
429insufficient_quotaNot enough credit; the message carries the address to top up at.
429key_daily_limit_reachedThe daily ceiling you set on this key is used up.
429key_monthly_limit_reachedThe monthly ceiling on this key is used up.
429rate_limit_exceededToo many requests a minute for this key (Retry-After says how many seconds to wait), or three agent runs already going.
500internal_errorAn internal error; nothing was charged.
502upstream_errorThe model's provider failed or could not be reached; try again.
503model_unavailableThis model is temporarily unavailable.

Limits

  • Requests a minute per key: 60 by default; set it anywhere from 1 to 6,000 when you make or edit the key in the panel. Beyond it, 429 with a Retry-After header.
  • An optional daily and monthly credit ceiling per key, set in the panel; GET /v1/balance shows what is left of it.
  • Optional on each key: allowed IP addresses (IPv4, IPv6 or a CIDR range), the groups of endpoints it may call, an end date, and switching it off for a while.
  • At most three agent runs at once per account.
  • Transcription files up to 25 MB; speech input up to 4,096 characters; up to 10 pictures a request; video edits of 1 to 120 seconds.
  • Each request's cost comes back in the x-deepfa-credits header and its id in x-deepfa-request-id; quote that id when you contact support.

Optional headers

  • X-DeepFA-Tag: a label of up to 64 characters for each request (a project, a department, one of your customers); the usage page and its Excel sheet break the spending down by it. Percent-encode a non-Latin label, since most libraries take only Latin letters in a header.
  • Idempotency-Key: send the same request again with the same key within a day (after a dropped connection, say) and the first answer comes back with Idempotent-Replayed: true; the request is not run or charged again. A streamed answer is not played back; its key only keeps it from running twice.

For tools and monitoring

Code Examples

Quick Start in 6 Programming Languages

The same request in six languages. The only things that differ from OpenAI are the base URL and the key.

curl https://deepfa.ir/api/v1/chat/completions \
  -H "Authorization: Bearer $DEEPFA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "messages": [{"role": "user", "content": "Hello"}]
  }'
# pip install openai
from openai import OpenAI

client = OpenAI(
    api_key="YOUR_DEEPFA_KEY",
    base_url="https://deepfa.ir/api/v1",
)

completion = client.chat.completions.create(
    model="claude-sonnet-5",
    messages=[{"role": "user", "content": "Hello"}],
)

print(completion.choices[0].message.content)
print(completion.usage.total_tokens, "tokens")
// Any fetch, no SDK needed.
const res = await fetch('https://deepfa.ir/api/v1/chat/completions', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${DEEPFA_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    model: 'gpt-6.1-sol',
    messages: [{ role: 'user', content: 'Hello' }],
    stream: false
  })
});

const data = await res.json();
console.log(data.choices[0].message.content);

// What the call cost, straight off the response header.
console.log(res.headers.get('x-deepfa-credits'), 'credits');
// npm install openai
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.DEEPFA_API_KEY,
  baseURL: 'https://deepfa.ir/api/v1'
});

// Streaming works exactly as it does upstream.
const stream = await client.chat.completions.create({
  model: 'gemini-3.8-flash',
  messages: [{ role: 'user', content: 'Write a haiku' }],
  stream: true
});

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? '');
}
<?php

$ch = curl_init('https://deepfa.ir/api/v1/chat/completions');

curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . getenv('DEEPFA_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'model'    => 'deepseek-flash',
        'messages' => [['role' => 'user', 'content' => 'Hello']],
    ]),
]);

$result = json_decode(curl_exec($ch), true);
curl_close($ch);

echo $result['choices'][0]['message']['content'];
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
    "os"
)

func main() {
    body, _ := json.Marshal(map[string]any{
        "model": "claude-haiku-5-5",
        "messages": []map[string]string{
            {"role": "user", "content": "Hello"},
        },
    })

    req, _ := http.NewRequest("POST",
        "https://deepfa.ir/api/v1/chat/completions",
        bytes.NewBuffer(body))

    req.Header.Set("Authorization", "Bearer "+os.Getenv("DEEPFA_API_KEY"))
    req.Header.Set("Content-Type", "application/json")

    res, _ := http.DefaultClient.Do(req)
    defer res.Body.Close()

    var out map[string]any
    json.NewDecoder(res.Body).Decode(&out)
    fmt.Println(out["choices"])
}
Sample JSON Responses
Chat Completion Response
{
  "id": "chatcmpl-9f2c1a",
  "object": "chat.completion",
  "model": "claude-sonnet-5",
  "choices": [{
    "index": 0,
    "message": { "role": "assistant", "content": "Hello!" },
    "finish_reason": "stop"
  }],
  "usage": {
    "prompt_tokens": 12,
    "completion_tokens": 306,
    "total_tokens": 318
  }
}
One Streamed Chunk
data: {"id":"chatcmpl-9f2c1a","object":"chat.completion.chunk",
"choices":[{"delta":{"content":"Hel"},"index":0}]}

data: [DONE]
Embeddings Response
{
  "object": "list",
  "model": "text-embedding-3-small",
  "data": [{ "object": "embedding", "index": 0,
             "embedding": [0.0021, -0.0134, 0.0075] }],
  "usage": { "prompt_tokens": 8, "total_tokens": 8 }
}
Image Generation Response
{
  "created": 1788115200,
  "data": [{ "b64_json": "iVBORw0KGgoAAAANSUhEUgAA..." }]
}
Cost Headers on Every Response
x-deepfa-request-id: 3f9a1c2e-...
x-deepfa-credits: 0.0954
x-deepfa-credit-unit: credits
Error Response, in OpenAI Shape
{
  "error": {
    "message": "You have run out of credit. Top up your balance to continue: https://deepfa.ir/app/user/pricing/plans#api_packs",
    "type": "insufficient_quota",
    "param": null,
    "code": "insufficient_quota"
  }
}
Getting Started

Send your first request in four simple steps

From creating a key to the first answer in under a minute. No app registration, no OAuth dance.

1

Create an API key

Sign in, open the API page and create a key. The key is shown once, so copy it there and then.

2

Point the base URL at DeepFA

In whatever tool or library you already use, set the base URL to https://deepfa.ir/api/v1 and paste the key as the API key.

3

Choose a model

Put the model name in the same model field — claude-sonnet-5-5, gpt-6.1-sol, gemini-3.8-flash or any other your key allows.

4

Watch what it costs

The cost of each call comes back in the x-deepfa-credits header and is recorded on the API page by key and by model.

Quick start
# 1 — the key you made on the API page export DEEPFA_API_KEY="sk-dfa-..." # 2 — the only two things that differ from OpenAI curl https://deepfa.ir/api/v1/chat/completions \ -H "Authorization: Bearer $DEEPFA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"claude-sonnet-5", "messages":[{"role":"user","content":"Hello"}]}' # 3 — the answer, in the shape you already parse { "choices": [{ "message": { "content": "Hello!" } }], "usage": { "total_tokens": 318 } } # 4 — what it cost, on the response itself x-deepfa-credits: 0.0954 x-deepfa-credit-unit: credits
Tool Screenshots

A Look Inside the API Interface

Simple and practical interface — click any image to enlarge.

FAQ

Frequently Asked Questions About the DeepFA AI API

Answers to common developer questions about using the API — contact support if you don't find your answer.

An account and an API key. You create the key on the API page in your dashboard and it works immediately — there is no app registration, no OAuth dance and no waiting for approval. Then set the base URL to https://deepfa.ir/api/v1 and give the key to any tool that speaks the OpenAI API. The first request usually takes under a minute.
Yes. The /v1/chat/completions path, the request body, the response shape, SSE streaming, tool calling and the error format all follow the OpenAI standard. Only two things change: the base URL and the key. That is what lets the official OpenAI libraries for Python and JavaScript, VS Code extensions such as Continue and Cline, Cursor and similar tools connect without a single line of change.
GPT, Claude, Gemini, Grok and DeepSeek models are all available from one address, with GPT Image, FLUX and Nano Banana for pictures, models such as Veo, Kling, Seedance and Grok Imagine for video, and Suno V6, Lyria 3.5, MiniMax Music 2.5 for music. Text is charged on the input and output tokens of the model you chose, and every model rate is listed in the price table on this page. Images are charged per image, video by length and resolution, transcription per minute and text-to-speech per character. The exact cost of each call comes back in the x-deepfa-credits response header.
Yes. When requests start the same way, like the fixed system prompt of a chatbot, that part is read from the cache of the model and charged at the cached input rate in the price table, a tenth of the normal input rate or less. It is automatic on GPT, Gemini and DeepSeek; for Claude, add cache_control with type ephemeral to the request. The number of cached tokens comes back in usage.prompt_tokens_details.cached_tokens.
Yes. Each key can carry a daily and a monthly credit ceiling, a per-minute request limit, allow-lists of models and endpoints, allowed IP addresses (IPv4, IPv6 or a CIDR range) and an end date, and it can be switched off for a while. A key you hand to a script or a colleague spends only up to that ceiling, and it can be revoked in one click if it leaks. Usage is reported per key on the API page, and any period can be downloaded as an Excel file.
No. API packs are sold at a far thinner margin, so they are spendable through an API key only and are not available in the tools inside the dashboard. The reverse does work: if your API credit runs out, requests continue against your plan and prepaid balance. Bought credit never expires.
Yes. Claude Code speaks Anthropic's Messages API, which DeepFA serves at /v1/messages: in the Claude Code settings file, set ANTHROPIC_BASE_URL to https://deepfa.ir/api and ANTHROPIC_AUTH_TOKEN to your DeepFA key. Codex speaks only OpenAI's Responses API, which DeepFA serves at /v1/responses: in config.toml, define a model_provider with base_url https://deepfa.ir/api/v1 and wire_api responses. Claude Code is for Claude models and Codex for OpenAI models; every other model is available through /v1/chat/completions.
Your code keeps working. When a model gives way to a newer one, requests that name the old model are answered by its replacement and charged at its price, and you are told once by email and in the dashboard so you can change the name when it suits you. The replaced names are listed on the Models tab of the API page. You are also emailed before your API credit runs out.
The Batch API: put the requests in a JSONL file (one request a line, each with a custom_id), upload it with POST /v1/files, start it with POST /v1/batches, and when its status is completed download the answers from GET /v1/files/{id}/content. The requests run in the background within 24 hours, each charged exactly as the same live request would be, and OpenAI's official library works with it unchanged.
Yes. On the Connect tab of the API page, give an https address as your webhook. When a video, a song, a podcast, an agent run or a batch ends, an event such as video.completed is posted to it, signed with HMAC, and tried again for about a day until your server answers 2xx.
Not if you send an Idempotency-Key header. With the same key and the same request within a day, the first answer comes back (with Idempotent-Replayed: true) and the request is not run or charged again. The service's state now and over the last ninety days is on the API status page.

Get Your API Key and Start Building Today

Free sign-up, a key in seconds, and credit that never expires

DeepFA AI screenshot preview