# deAPI > Decentralized AI inference API. One unified REST API for image generation, video generation (from text, image, or audio), video character replacement (animate), video upscaling, audio synthesis, music creation, transcription, OCR, embeddings, and more. - Base URL: `https://deapi.ai` - Docs: [docs.deapi.ai](https://docs.deapi.ai) - Dashboard: [app.deapi.ai/dashboard](https://app.deapi.ai/dashboard) - Status: [status.deapi.ai](https://status.deapi.ai) - GitHub: [github.com/deapi-ai](https://github.com/deapi-ai) ## Authentication All requests require a Bearer token in the `Authorization` header and `Accept: application/json`. ``` Authorization: Bearer YOUR_API_KEY Accept: application/json ``` Get your API key at [app.deapi.ai/dashboard/api-keys](https://app.deapi.ai/dashboard/api-keys). New accounts receive $5 free credits. ## Dynamic Model Discovery **Never hardcode model names.** Use the models endpoint to discover available models at runtime. ### GET /api/v1/client/models Returns all available models. Filter by inference type to get models for a specific task. Query parameters: - `filter[inference_types]` — Comma-separated list of inference types to filter by. Values: `txt2img`, `img2txt`, `txt2audio`, `aud2txt`, `vid2txt`, `audiofile2txt`, `videofile2txt`, `transcribe`, `txt2video`, `img2video`, `aud2video`, `img2img`, `img_upscale`, `img_rmbg`, `vid_upscale`, `txt2embedding`, `txt2music`, `videos_replace`. Example: `filter[inference_types]=txt2img,img2img` - `per_page` — Number of models per page (default: 25) - `page` — Page number for pagination The response is paginated with `data`, `links`, and `meta` fields. Each model in `data` has this schema: ```json { "name": "FLUX.1 Schnell 12B NF4", "slug": "Flux1schnell", "inference_types": ["txt2img"], "info": { "limits": { "min_width": 256, "max_width": 2048, "min_height": 256, "max_height": 2048, "min_steps": 1, "max_steps": 10, "resolution_step": 128 }, "features": { "supports_steps": true, "supports_guidance": false, "supports_negative_prompt": true, "supports_last_frame": false, "supports_custom_output_size": false }, "defaults": { "width": 768, "height": 768, "steps": 4, "negative_prompt": "Negative prompt" } }, "loras": [ { "display_name": "LoRA Display Name", "name": "LoraSlug" } ], "languages": null } ``` Notes: - `loras` is null for models without LoRA support, or an array of `{display_name, name}` objects listing available LoRAs. In generation requests, use `loras: [{"name": "LoraSlug", "weight": 0.8}]`. - `features` fields vary by model type: image models have `supports_guidance`, `supports_steps`, `supports_negative_prompt`; video models add `supports_last_frame`; TTS models have `supports_voice_clone`, `supports_custom_voice`, `supports_voice_design`; video upscale models may expose `supports_scale`. - `limits` fields vary by model type: image models have width/height/steps limits; music models have `min_caption`/`max_caption`, `min_duration`/`max_duration`, `min_bpm`/`max_bpm`; TTS models have `min_text`/`max_text`, `min_speed`/`max_speed`, `available_ratios`; embedding models have `max_input_tokens`/`max_total_tokens`; video upscale models may have `min_scale`/`max_scale`. For TTS models, `languages` contains an array of supported languages with voice presets: ```json { "languages": [ { "name": "English (US)", "slug": "en-us", "voices": [ { "name": "Alloy", "slug": "af_alloy", "gender": "male" } ] } ] } ``` ### Python Example: Fetching and Caching Models ```python import requests import time class DeAPIModelCache: """Cache model list with TTL to avoid redundant API calls.""" def __init__(self, api_key, cache_ttl=300): self.api_key = api_key self.base_url = "https://api.deapi.ai" self.headers = { "Authorization": f"Bearer {api_key}", "Accept": "application/json" } self.cache_ttl = cache_ttl # seconds (default: 5 minutes) self._cache = {} self._cache_ts = {} def get_models(self, inference_type=None, force_refresh=False): cache_key = inference_type or "__all__" now = time.time() if (not force_refresh and cache_key in self._cache and now - self._cache_ts[cache_key] < self.cache_ttl): return self._cache[cache_key] params = {} if inference_type: params["filter[inference_types]"] = inference_type resp = requests.get( f"{self.base_url}/api/v1/client/models", headers=self.headers, params=params ) resp.raise_for_status() models = resp.json()["data"] self._cache[cache_key] = models self._cache_ts[cache_key] = now return models def get_model_slugs(self, inference_type): """Return list of model slugs for a given task type.""" return [m["slug"] for m in self.get_models(inference_type)] ``` ### Model Fallback Strategy When a model is unavailable or returns errors, fall back to another model of the same inference type: ```python import requests import time class DeAPIClient: def __init__(self, api_key): self.api_key = api_key self.base_url = "https://api.deapi.ai" self.headers = { "Authorization": f"Bearer {api_key}", "Accept": "application/json" } self.model_cache = DeAPIModelCache(api_key) def generate_with_fallback(self, endpoint, payload, inference_type): """Try each available model until one succeeds.""" models = self.model_cache.get_models(inference_type) last_error = None for model in models: payload["model"] = model["slug"] try: resp = requests.post( f"{self.base_url}{endpoint}", headers=self.headers, json=payload ) if resp.status_code == 429: self._handle_rate_limit(resp) continue resp.raise_for_status() return resp.json() except requests.exceptions.RequestException as e: last_error = e # Refresh model list in case availability changed self.model_cache.get_models(inference_type, force_refresh=True) continue raise last_error or Exception("All models failed") def _handle_rate_limit(self, resp): retry_after = int(resp.headers.get("Retry-After", 5)) time.sleep(retry_after) ``` ## Rate Limit Handling ### Rate Limit Tiers | Tier | Activation | RPM | Daily Limit | |---|---|---|---| | Basic | Free $5 credit | 1-10 per endpoint | 15-100 per endpoint | | Premium | Any payment made | 300 | Unlimited | ### 429 Response Headers When rate limited, the API returns HTTP 429 with these headers: | Header | Description | |---|---| | `X-RateLimit-Limit` | Maximum requests per minute | | `X-RateLimit-Remaining` | Remaining requests in current window | | `X-RateLimit-Daily-Limit` | Maximum daily requests | | `X-RateLimit-Daily-Remaining` | Remaining daily requests | | `X-RateLimit-Type` | Which limit was hit: `"minute"` or `"daily"` | | `Retry-After` | Seconds until the limit resets | Response body: `{ "message": "Too Many Attempts." }` ### Retry with Exponential Backoff ```python import requests import time import random def request_with_retry(url, headers, payload=None, method="post", max_retries=5, content_type="json"): for attempt in range(max_retries): if method == "post": if content_type == "json": resp = requests.post(url, headers=headers, json=payload) else: resp = requests.post(url, headers=headers, data=payload) else: resp = requests.get(url, headers=headers, params=payload) if resp.status_code != 429: resp.raise_for_status() return resp.json() limit_type = resp.headers.get("X-RateLimit-Type", "minute") retry_after = int(resp.headers.get("Retry-After", 5)) if limit_type == "daily": raise Exception("Daily rate limit reached. Try again tomorrow.") # Exponential backoff with jitter, respecting Retry-After wait = max(retry_after, (2 ** attempt) + random.uniform(0, 1)) time.sleep(wait) raise Exception("Max retries exceeded") ``` ## Generation Endpoints All generation endpoints return `{ "data": { "request_id": "UUID" } }`. Use the request_id to poll for results or receive them via webhook/WebSocket. ### POST /api/v1/client/txt2img — Text to Image Content-Type: `application/json` | Parameter | Type | Required | Description | |---|---|---|---| | `prompt` | string | Yes | Text description of the image to generate | | `model` | string | Yes | Model slug from /models endpoint | | `width` | integer | Yes | Image width in pixels | | `height` | integer | Yes | Image height in pixels | | `guidance` | number | Yes | CFG scale / guidance strength | | `steps` | integer | Yes | Number of inference steps | | `seed` | integer | Yes | Random seed (-1 for random) | | `negative_prompt` | string | No | What to avoid in the image | | `loras` | array | No | LoRA weights: `[{"name": "lora_slug", "weight": 0.8}]` | | `webhook_url` | string | No | HTTPS URL for status notifications (max 2048 chars) | ### POST /api/v1/client/img2img — Image to Image Content-Type: `multipart/form-data` | Parameter | Type | Required | Description | |---|---|---|---| | `prompt` | string | Yes | Text description for transformation | | `model` | string | Yes | Model slug | | `steps` | integer | Yes | Inference steps | | `seed` | integer | Yes | Random seed | | `image` | file | Yes* | Source image (max 10MB). Mutually exclusive with `images[]` | | `images[]` | file[] | Yes* | Multiple source images. Mutually exclusive with `image` | | `negative_prompt` | string | No | What to avoid | | `width` | integer | No | Output width | | `height` | integer | No | Output height | | `guidance` | number | No | CFG scale | | `loras` | array | No | LoRA weights | | `webhook_url` | string | No | HTTPS webhook URL | ### POST /api/v1/client/txt2audio — Text to Speech Content-Type: `multipart/form-data` | Parameter | Type | Required | Description | |---|---|---|---| | `text` | string | Yes | Text to synthesize | | `model` | string | Yes | Model slug (e.g. `Kokoro`) | | `lang` | string | Yes | Language code | | `speed` | number | Yes | Speech speed multiplier | | `format` | string | Yes | Output format (mp3, wav, etc.) | | `sample_rate` | integer | Yes | Audio sample rate in Hz | | `mode` | string | No | `custom_voice`, `voice_clone`, or `voice_design` | | `voice` | string | No | Voice preset slug (for `custom_voice` mode) | | `ref_audio` | file | No | Reference audio for voice cloning (3-10s, max 10MB). Required for voice_clone mode | | `ref_text` | string | No | Transcript of reference audio | | `instruct` | string | No | Voice design instructions | | `webhook_url` | string | No | HTTPS webhook URL | ### POST /api/v1/client/txt2video — Text to Video Content-Type: `application/json` | Parameter | Type | Required | Description | |---|---|---|---| | `prompt` | string | Yes | Video description | | `model` | string | Yes | Model slug | | `width` | integer | Yes | Video width | | `height` | integer | Yes | Video height | | `guidance` | number | Yes | CFG scale | | `steps` | integer | Yes | Inference steps | | `seed` | integer | Yes | Random seed | | `frames` | integer | Yes | Number of frames | | `negative_prompt` | string | No | What to avoid | | `fps` | integer | No | Frames per second | | `webhook_url` | string | No | HTTPS webhook URL | ### POST /api/v1/client/img2video — Image to Video Content-Type: `multipart/form-data` | Parameter | Type | Required | Description | |---|---|---|---| | `prompt` | string | Yes | Video description | | `first_frame_image` | file | Yes | Starting frame image (max 10MB) | | `model` | string | Yes | Model slug | | `width` | integer | Yes | Video width | | `height` | integer | Yes | Video height | | `guidance` | number | Yes | CFG scale | | `steps` | integer | Yes | Inference steps | | `seed` | integer | Yes | Random seed | | `frames` | integer | Yes | Number of frames | | `negative_prompt` | string | No | What to avoid | | `fps` | integer | No | Frames per second | | `last_frame_image` | file | No | Ending frame image (max 10MB) | | `webhook_url` | string | No | HTTPS webhook URL | ### POST /api/v1/client/aud2video — Audio to Video Content-Type: `multipart/form-data` | Parameter | Type | Required | Description | |---|---|---|---| | `prompt` | string | Yes | Video description | | `audio` | file | Yes | Audio file to condition the video generation (MP3, WAV, OGG, FLAC; max 20MB) | | `model` | string | Yes | Model slug (e.g. `Ltx2_19B_Dist_FP8`) | | `width` | integer | Yes | Video width in pixels | | `height` | integer | Yes | Video height in pixels | | `seed` | integer | Yes | Random seed | | `frames` | integer | Yes | Number of frames | | `guidance` | number | No | CFG scale | | `steps` | integer | No | Inference steps | | `fps` | integer | No | Frames per second | | `negative_prompt` | string | No | What to avoid | | `first_frame_image` | file | No | Starting frame image (max 10MB) | | `last_frame_image` | file | No | Ending frame image (max 10MB) | | `webhook_url` | string | No | HTTPS webhook URL | ### POST /api/v1/client/txt2music — Text to Music Content-Type: `multipart/form-data` | Parameter | Type | Required | Description | |---|---|---|---| | `caption` | string | Yes | Music description / style prompt | | `model` | string | Yes | Model slug (e.g. `ACE-Step-v1.5-turbo`) | | `lyrics` | string | Yes | Song lyrics. Use `"[Instrumental]"` for no vocals | | `duration` | number | Yes | Duration in seconds (10-600) | | `inference_steps` | integer | Yes | Steps (1-100; 8 for turbo models, 32+ for base models) | | `guidance_scale` | number | Yes | Guidance scale (0-20) | | `seed` | integer | Yes | Random seed (-1 for random) | | `format` | string | Yes | Output format (e.g. `flac`) | | `bpm` | integer | No | Beats per minute (30-300) | | `keyscale` | string | No | Musical key and scale (e.g. `"C major"`, `"F# minor"`) | | `timesignature` | integer | No | Time signature: 2, 3, 4, or 6 | | `vocal_language` | string | No | Vocal language code (e.g. `"en"`, `"es"`) | | `reference_audio` | file | No | Reference audio file for style transfer (mp3, wav, flac, ogg, m4a; max 10MB) | | `webhook_url` | string | No | HTTPS webhook URL | ### POST /api/v1/client/txt2embedding — Text to Embedding Content-Type: `application/json` | Parameter | Type | Required | Description | |---|---|---|---| | `input` | string or array | Yes | Text(s) to embed. Max 2048 items, 8192 tokens per input, 300K total tokens | | `model` | string | Yes | Model slug (e.g. `Bge_M3_FP16`) | | `return_result_in_response` | boolean | No | Return embeddings directly instead of via polling | | `webhook_url` | string | No | HTTPS webhook URL | ## Analysis Endpoints ### POST /api/v1/client/transcribe — Unified Transcription (NEW — recommended) Content-Type: `multipart/form-data` A single endpoint for all transcription needs. Accepts either a source URL or a file upload — the job type is auto-detected. Replaces the four legacy endpoints (`vid2txt`, `aud2txt`, `videofile2txt`, `audiofile2txt`) which remain fully operational. | Parameter | Type | Required | Description | |---|---|---|---| | `source_url` | string | One of* | URL to transcribe (YouTube, X/Twitter, Twitch, Kick, TikTok, X Spaces). Mutually exclusive with `source_file` | | `source_file` | file | One of* | Audio or video file to transcribe. Supported audio: AAC, MPEG, OGG, WAV, WebM, FLAC. Supported video: MP4, MPEG, QuickTime, AVI, WMV, OGG. Mutually exclusive with `source_url` | | `include_ts` | boolean | Yes | Include timestamps in transcription | | `model` | string | Yes | Model slug (e.g. `WhisperLargeV3`) | | `return_result_in_response` | boolean | No | Return transcription directly in the response instead of download URL | | `webhook_url` | string | No | HTTPS webhook URL | \* Provide exactly one of `source_url` or `source_file`. ### POST /api/v1/client/img2txt — Image to Text (OCR) Content-Type: `multipart/form-data` | Parameter | Type | Required | Description | |---|---|---|---| | `image` | file | Yes | Image file (max 10MB) | | `model` | string | Yes | Model slug (e.g. `Nanonets_Ocr_S_F16`) | | `language` | string | No | Target language | | `format` | string | No | Output format: `text` or `json` | | `return_result_in_response` | boolean | No | Return result directly | | `webhook_url` | string | No | HTTPS webhook URL | ### POST /api/v1/client/vid2txt — Video URL to Text (legacy) Content-Type: `application/json` Transcribes video from URL (YouTube, X/Twitter, Twitch, Kick, TikTok). Consider using the unified `/transcribe` endpoint for new integrations. | Parameter | Type | Required | Description | |---|---|---|---| | `video_url` | string | Yes | Video URL (YouTube, X, Twitch, Kick, TikTok) | | `include_ts` | boolean | Yes | Include timestamps in transcription | | `model` | string | No | Model slug (e.g. `WhisperLargeV3`) | | `return_result_in_response` | boolean | No | Return result directly | | `webhook_url` | string | No | HTTPS webhook URL | ### POST /api/v1/client/videofile2txt — Video File to Text (legacy) Content-Type: `multipart/form-data` Consider using the unified `/transcribe` endpoint for new integrations. | Parameter | Type | Required | Description | |---|---|---|---| | `video` | file | Yes | Video file (MP4, MPEG, MOV, AVI, WMV, OGG; max 10MB; must contain audio) | | `include_ts` | boolean | Yes | Include timestamps | | `model` | string | No | Model slug (e.g. `WhisperLargeV3`) | | `return_result_in_response` | boolean | No | Return result directly | | `webhook_url` | string | No | HTTPS webhook URL | ### POST /api/v1/client/aud2txt — Audio URL to Text / X Spaces (legacy) Content-Type: `application/json` Consider using the unified `/transcribe` endpoint for new integrations. | Parameter | Type | Required | Description | |---|---|---|---| | `audio_url` | string | Yes | Twitter/X Spaces URL | | `include_ts` | boolean | Yes | Include timestamps | | `model` | string | Yes | Model slug (e.g. `WhisperLargeV3`) | | `return_result_in_response` | boolean | No | Return result directly | | `webhook_url` | string | No | HTTPS webhook URL | ### POST /api/v1/client/audiofile2txt — Audio File to Text (legacy) Content-Type: `multipart/form-data` Consider using the unified `/transcribe` endpoint for new integrations. | Parameter | Type | Required | Description | |---|---|---|---| | `audio` | file | Yes | Audio file (AAC, MP3, OGG, WAV, WebM, FLAC; max 10MB) | | `include_ts` | boolean | Yes | Include timestamps | | `model` | string | No | Model slug (e.g. `WhisperLargeV3`) | | `return_result_in_response` | boolean | No | Return result directly | | `webhook_url` | string | No | HTTPS webhook URL | ## Transformation Endpoints ### POST /api/v1/client/img-rmbg — Image Background Removal Content-Type: `multipart/form-data` | Parameter | Type | Required | Description | |---|---|---|---| | `image` | file | Yes | Image file (max 10MB) | | `model` | string | Yes | Model slug (e.g. `Ben2`) | | `webhook_url` | string | No | HTTPS webhook URL | ### POST /api/v1/client/img-upscale — Image Upscale Content-Type: `multipart/form-data` | Parameter | Type | Required | Description | |---|---|---|---| | `image` | file | Yes | Image file to upscale | | `model` | string | Yes | Model slug (e.g. `RealESRGAN_x4`) | | `webhook_url` | string | No | HTTPS webhook URL | ### POST /api/v1/client/vid-upscale — Video Upscale (NEW) Content-Type: `multipart/form-data` Upscales a video to higher resolution. Some models support a configurable `scale` factor; fixed-scale models reject the parameter. | Parameter | Type | Required | Description | |---|---|---|---| | `video` | file | Yes | Input video file (MP4, MPEG, QuickTime, AVI, WMV, OGG; max 10MB) | | `model` | string | Yes | Model slug from /models endpoint | | `scale` | integer | No | Upscale factor (1-16). Only accepted on models with `supports_scale`; fixed-scale models reject this field | | `webhook_url` | string | No | HTTPS webhook URL (max 2048 chars) | ### POST /api/v1/client/videos/replace — Video Replace (Animate) (NEW) Content-Type: `multipart/form-data` Replaces a person in a video with a character from a reference image. Ideal for character animation, face swap, and creative video editing. | Parameter | Type | Required | Description | |---|---|---|---| | `video` | file | Yes | Input video file (MP4, MPEG, QuickTime, AVI, WMV, OGG) | | `ref_image` | file | Yes | Reference character image (JPG, JPEG, PNG, GIF, BMP, WebP; max 10MB) | | `model` | string | Yes | Model slug from /models endpoint | | `prompt` | string | No | Text prompt to guide the replacement | | `width` | integer | No | Output video width (defaults to input width). Must be provided together with height | | `height` | integer | No | Output video height (defaults to input height). Must be provided together with width | | `steps` | integer | No | Inference steps (default: 4) | | `seed` | integer | No | Random seed (default: -1 for random) | | `webhook_url` | string | No | HTTPS webhook URL (max 2048 chars) | ## Prompt Enhancement Improve prompts before generation for better results. All prompt endpoints return enhanced prompts. ### POST /api/v1/client/prompt/image — Image Prompt Booster Content-Type: `application/json` | Parameter | Type | Required | Description | |---|---|---|---| | `prompt` | string | Yes | Original prompt (min 3 characters) | | `negative_prompt` | string | Yes | Original negative prompt (min 3 chars). Must be present in request. | Response: `{ "prompt": "enhanced prompt", "negative_prompt": "enhanced negative" }` ### POST /api/v1/client/prompt/image2image — Image-to-Image Prompt Booster Content-Type: `multipart/form-data` | Parameter | Type | Required | Description | |---|---|---|---| | `prompt` | string | Yes | Original prompt | | `image` | file | Yes | Reference image | | `negative_prompt` | string | Yes | Original negative prompt. Must be present in request. | ### POST /api/v1/client/prompt/video — Video Prompt Booster Content-Type: `multipart/form-data` | Parameter | Type | Required | Description | |---|---|---|---| | `prompt` | string | Yes | Original video prompt | | `negative_prompt` | string | Yes | Negative prompt. Must be present in request. | | `image` | file | No | Optional reference image for context-aware enhancement | ### POST /api/v1/client/prompt/speech — Speech Prompt Booster Content-Type: `application/json` | Parameter | Type | Required | Description | |---|---|---|---| | `prompt` | string | Yes | Text to enhance for speech | | `lang_code` | string | No | Language code | Response: `{ "prompt": "enhanced text" }` ### GET /api/v1/client/prompts/samples — Sample Prompts | Parameter | Type | Required | Description | |---|---|---|---| | `type` | string | Yes | Prompt type: `text2image` or `text2speech` | | `topic` | string | No | Topic to generate samples for (max 500 chars) | | `lang_code` | string | No | Language code (max 4 chars) | Response: `{ "success": true, "data": { "type": "text2image", "prompt": "sample prompt text" } }` ## Price Calculation Every endpoint has a corresponding `/price-calculation` POST endpoint that accepts the same parameters and returns the cost before execution. **Pattern:** `POST /api/v1/client/{endpoint}/price-calculation` Generation/analysis/transformation endpoints return: `{ "data": { "price": 0.00187 } }` Prompt enhancement endpoints return: `{ "price": 0.0008728 }` Notes on price calculation parameters: - `img2img/price-calculation` uses `Content-Type: application/json` (not multipart like the main endpoint). - `txt2audio/price-calculation` accepts `count_text` (integer) as an alternative to `text` — pass the character count instead of the full text. - `transcribe/price-calculation` accepts `source_url`, `source_file`, or `duration_seconds` (mutually exclusive) — pass duration in seconds for price estimation without a URL or file. - `aud2txt/price-calculation` accepts `duration_seconds` (number) as an alternative to `audio_url` — pass the duration in seconds for price estimation without a URL. - `videofile2txt/price-calculation` and `audiofile2txt/price-calculation` accept `duration_seconds` as an alternative to the file upload. - `vid-upscale/price-calculation` accepts `video`+`model`+optional `scale`, OR `width`+`height`+`model`+optional `duration`+optional `scale`. Price is not duration-dependent; duration is only validated against the model's configured maximum. - `videos/replace/price` accepts `video` file or `duration` + `width`/`height` — pass video dimensions and duration for price estimation without uploading. Available price calculation endpoints: - `/api/v1/client/txt2img/price-calculation` - `/api/v1/client/txt2audio/price-calculation` - `/api/v1/client/txt2video/price-calculation` - `/api/v1/client/img2video/price-calculation` - `/api/v1/client/aud2video/price-calculation` - `/api/v1/client/txt2music/price-calculation` - `/api/v1/client/txt2embedding/price-calculation` - `/api/v1/client/img2txt/price-calculation` - `/api/v1/client/transcribe/price-calculation` - `/api/v1/client/vid2txt/price-calculation` - `/api/v1/client/videofile2txt/price-calculation` - `/api/v1/client/aud2txt/price-calculation` - `/api/v1/client/audiofile2txt/price-calculation` - `/api/v1/client/img2img/price-calculation` - `/api/v1/client/img-rmbg/price-calculation` - `/api/v1/client/img-upscale/price-calculation` - `/api/v1/client/vid-upscale/price-calculation` - `/api/v1/client/videos/replace/price` - `/api/v1/client/prompt/image/price-calculation` - `/api/v1/client/prompt/image2image/price-calculation` - `/api/v1/client/prompt/video/price-calculation` - `/api/v1/client/prompt/speech/price-calculation` - `GET /api/v1/client/prompts/samples/price-calculation` ## Result Delivery deAPI supports three methods to receive job results: polling, WebSockets, and webhooks. ### Polling Poll the job status endpoint until `status` is `done` or `error`. #### GET /api/v1/client/request-status/{request_id} Response: ```json { "data": { "status": "done", "preview": "base64_string_or_null", "result_url": "https://storage.deapi.ai/...", "results_alt_formats": null, "result": "text_result_or_null", "progress": 100.0 } } ``` Notes: `results_alt_formats` is null or an object with `jpg`/`webp` URLs when available. `preview` is a base64-encoded thumbnail (available during processing and on completion). `result` contains text output for transcription/OCR endpoints; `result_url` contains the file URL for generation endpoints. Status values: `pending` → `processing` → `done` | `error` ```python import requests import time def poll_job(api_key, request_id, interval=2, timeout=300): """Poll for job completion with adaptive intervals.""" url = f"https://api.deapi.ai/api/v1/client/request-status/{request_id}" headers = { "Authorization": f"Bearer {api_key}", "Accept": "application/json" } start = time.time() while time.time() - start < timeout: resp = requests.get(url, headers=headers) resp.raise_for_status() data = resp.json()["data"] if data["status"] == "done": return data if data["status"] == "error": raise Exception(f"Job {request_id} failed") # Adaptive polling: longer waits as job progresses progress = data.get("progress", 0) if progress > 50: time.sleep(interval) else: time.sleep(interval * 2) raise TimeoutError(f"Job {request_id} timed out after {timeout}s") ``` ### WebSockets (Real-time) Connect to the Pusher-compatible WebSocket server for real-time status updates. - **Host:** `soketi.deapi.ai` - **Port:** 443 (WSS) - **App Key:** `depin-api-prod-key` - **Auth endpoint:** `POST https://api.deapi.ai/broadcasting/auth` - **Channel:** `private-client.{client_id}` - **Event:** `request.status.updated` Event payload: ```json { "request_id": "uuid", "status": "processing", "preview": "base64_or_null", "result_url": "https://storage.deapi.ai/...", "progress": 45.0 } ``` WebSocket status flow: `pending` → `processing` → `in_progress` → `done` Note: Error events are not sent via WebSocket — use webhooks to catch failures. Connection requirements: - Send ping every 30 seconds to keep connection alive - Implement reconnection with exponential backoff ### Webhooks Receive HTTP POST callbacks for job status changes. Configure globally in account settings or per-request via `webhook_url` parameter. Must be HTTPS. #### Security Headers Every webhook request includes these headers: | Header | Description | |---|---| | `X-DeAPI-Signature` | HMAC-SHA256 signature: `sha256=` | | `X-DeAPI-Timestamp` | Unix timestamp when the webhook was sent | | `X-DeAPI-Event` | Event type: `job.processing`, `job.completed`, or `job.failed` | | `X-DeAPI-Delivery-Id` | Unique delivery UUID (use for idempotency) | #### Signature Verification Compute: `HMAC-SHA256(key: webhook_secret, message: timestamp + "." + raw_json_payload)`. Reject timestamps older than 5 minutes to prevent replay attacks. #### Webhook Payloads All payloads share a common envelope: ```json { "event": "job.completed", "delivery_id": "550e8400-e29b-41d4-a716-446655440001", "timestamp": "2024-01-15T10:30:45.000Z", "data": { ... } } ``` **`job.processing`** — job started processing: ```json { "data": { "job_request_id": "123e4567-e89b-12d3-a456-426614174000", "status": "processing", "previous_status": "pending", "job_type": "txt2img", "started_at": "2024-01-15T10:30:00.000Z" } } ``` **`job.completed`** — job finished successfully: ```json { "data": { "job_request_id": "123e4567-e89b-12d3-a456-426614174000", "status": "done", "previous_status": "processing", "job_type": "txt2img", "completed_at": "2024-01-15T10:30:45.000Z", "result_url": "https://storage.deapi.ai/...", "processing_time_ms": 4500 } } ``` **`job.failed`** — job encountered an error: ```json { "data": { "job_request_id": "123e4567-e89b-12d3-a456-426614174000", "status": "error", "previous_status": "processing", "job_type": "txt2img", "failed_at": "2024-01-15T10:30:45.000Z", "error_code": "model_unavailable", "error_message": "The requested model is currently unavailable" } } ``` `job_type` values: `txt2img`, `img2img`, `txt2video`, `img2video`, `aud2video`, `txt2audio`, `txt2music`, `txt2embedding`, `img2txt`, `transcribe`, `vid2txt`, `videofile2txt`, `aud2txt`, `audiofile2txt`, `img_rmbg`, `img_upscale`, `vid_upscale`, `videos_replace`. #### Webhook Error Codes | Code | Description | |---|---| | `WORKER_TIMEOUT` | Worker timed out processing the job | | `PROCESSING_ERROR` | Error during inference processing | | `AGE_RESTRICTED` | Content flagged as age-restricted | | `CONTEXT_LENGTH_EXCEEDED` | Input exceeds model context length | | `INVALID_INPUT` | Invalid input parameters | | `UNKNOWN_ERROR` | Unclassified error | #### Webhook Requirements - Respond with 2xx within 10 seconds - No redirects - Retry policy: exponential backoff, 10 attempts over ~24 hours - Auto-disabled after 10 consecutive failures ## Utility Endpoints ### GET /api/v1/client/balance Returns current account balance. Response: `{ "data": { "balance": 4.52 } }` ### GET /api/v1/client/models See [Dynamic Model Discovery](#dynamic-model-discovery) section above. ### GET /api/v1/client/request-status/{request_id} See [Polling](#polling) section above. ## MCP Server Integration deAPI provides an MCP (Model Context Protocol) server for integration with AI assistants. - **MCP URL:** `https://mcp.deapi.ai/mcp` - **OAuth Client ID:** `deapi-mcp` - **Auth:** OAuth 2.0 or Bearer token - **Transport:** Streamed HTTP - **Status:** Alpha - **Source:** MIT-licensed at [github.com/deapi-ai/mcp-server-deapi](https://github.com/deapi-ai/mcp-server-deapi) ### Claude Desktop Configuration ```json { "mcpServers": { "deapi": { "url": "https://mcp.deapi.ai/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } ``` Compatible with: Claude Web, Claude Desktop, Cursor IDE, ChatGPT. The MCP server includes smart polling with adaptive intervals: audio 1-5s, images 2-8s, video 5-30s. ## Python SDK Official Python SDK: `pip install deapi-python-sdk` (Python 3.9+) Source: [github.com/deapi-ai/deapi-python-sdk](https://github.com/deapi-ai/deapi-python-sdk) Features: full API coverage (images, video, audio, TTS, voice cloning, music, transcription, embeddings, OCR, video upscale, prompt enhancement), sync and async clients (`DeapiClient` / `AsyncDeapiClient`), automatic job polling with exponential backoff (`.wait()`), auto-retry on rate limits (429) and server errors (5xx), type-safe with Pydantic v2, webhook signature verification, price calculation for every method. ```python from deapi import DeapiClient client = DeapiClient(api_key="sk-your-api-key") # Generate an image job = client.images.generate( prompt="a cat floating in a nebula, photorealistic", model="Flux_2_Klein_4B_BF16", width=1024, height=1024, steps=4, seed=-1, ) # Wait for the result (polls with exponential backoff) result = job.wait() print(result.result_url) ``` ## Pricing Pay-per-use, no subscriptions required. $5 free credits for new accounts. | Service | Price | |---|---| | Text-to-Image (512x512, 4 steps) | ~$0.0019/image | | Text-to-Image (1024x1024, 4 steps) | ~$0.0037/image | | Image-to-Image (4 steps) | ~$0.0066/transformation | | Text-to-Speech | $0.77/1M characters | | Text-to-Video (512x512, 4s) | ~$0.0056/video | | Image-to-Video (512x512, 4s) | ~$0.0056/video | | Text-to-Music | ~$0.0009/minute | | Video-to-Text | ~$0.021/hour | | Image-to-Text (OCR) | ~$0.0093/1K output chars | | Text-to-Embedding | ~$0.000068/1K tokens | | Image Background Removal (1920x1080) | ~$0.00046/image | | Image Upscale (512→2048, 4x) | ~$0.00059/image | | Video Upscale | Use `/vid-upscale/price-calculation` endpoint | | Video Replace (Animate) | Use `/videos/replace/price` endpoint | Prices are approximate and vary by model and parameters. Use the `/price-calculation` endpoints for exact costs before execution. File upload limit: up to 80MB per file (10MB for image, 80MB for aud2video audio), 600-minute maximum duration for audio/video. ## Complete Usage Example ```python import requests import time API_KEY = "your_api_key" BASE = "https://api.deapi.ai" HEADERS = { "Authorization": f"Bearer {API_KEY}", "Accept": "application/json" } # 1. Discover models for text-to-image models_resp = requests.get( f"{BASE}/api/v1/client/models", headers=HEADERS, params={"filter[inference_types]": "txt2img"} ) models = models_resp.json()["data"] model_slug = models[0]["slug"] defaults = models[0]["info"]["defaults"] # 2. Check price before generating payload = { "prompt": "a sunset over mountains", "model": model_slug, "width": defaults["width"], "height": defaults["height"], "steps": defaults["steps"], "guidance": 1, "seed": -1 } price_resp = requests.post( f"{BASE}/api/v1/client/txt2img/price-calculation", headers={**HEADERS, "Content-Type": "application/json"}, json=payload ) price = price_resp.json()["data"]["price"] print(f"Cost: ${price}") # 3. Generate image gen_resp = requests.post( f"{BASE}/api/v1/client/txt2img", headers={**HEADERS, "Content-Type": "application/json"}, json=payload ) request_id = gen_resp.json()["data"]["request_id"] # 4. Poll for result while True: status_resp = requests.get( f"{BASE}/api/v1/client/request-status/{request_id}", headers=HEADERS ) data = status_resp.json()["data"] if data["status"] == "done": print(f"Result: {data['result_url']}") break if data["status"] == "error": raise Exception("Generation failed") time.sleep(3) ``` ## Error Handling | HTTP Code | Meaning | Action | |---|---|---| | 401 | Unauthorized — invalid or missing API key | Check your API key | | 404 | Resource not found | Verify endpoint URL and request_id | | 422 | Validation error — invalid parameters | Check field-level error details in response | | 429 | Rate limited | Respect `Retry-After` header; see Rate Limit Handling | ## Links - API Documentation: [docs.deapi.ai](https://docs.deapi.ai) - Dashboard & API Keys: [app.deapi.ai/dashboard](https://app.deapi.ai/dashboard) - Sign Up: [app.deapi.ai/register](https://app.deapi.ai/register) - Sign In: [app.deapi.ai/login](https://app.deapi.ai/login) - Account Settings: [app.deapi.ai/settings/account](https://app.deapi.ai/settings/account) - API Keys: [app.deapi.ai/settings/api-keys](https://app.deapi.ai/settings/api-keys) - Webhooks Settings: [app.deapi.ai/settings/webhooks](https://app.deapi.ai/settings/webhooks) - Billing: [app.deapi.ai/billing](https://app.deapi.ai/billing) - Playground (Text to Image): [deapi.ai/playground/text-to-image](https://deapi.ai/playground/text-to-image) - Playground (Image to Image): [deapi.ai/playground/image-to-image](https://deapi.ai/playground/image-to-image) - Playground (Text to Speech): [deapi.ai/playground/text-to-speech](https://deapi.ai/playground/text-to-speech) - Playground (Image to Video): [deapi.ai/playground/image-to-video](https://deapi.ai/playground/image-to-video) - Playground (Video to Text): [deapi.ai/playground/video-to-text](https://deapi.ai/playground/video-to-text) - Playground (Image to Text / OCR): [deapi.ai/playground/image-to-text](https://deapi.ai/playground/image-to-text) - Playground (Text to Music): [deapi.ai/playground/text-to-music](https://deapi.ai/playground/text-to-music) - Models: [deapi.ai/models](https://deapi.ai/models) - Use Cases: [deapi.ai/use-cases](https://deapi.ai/use-cases) - Use Case — Text to Image: [deapi.ai/use-cases/text-to-image](https://deapi.ai/use-cases/text-to-image) - Use Case — Text to Speech: [deapi.ai/use-cases/text-to-speech](https://deapi.ai/use-cases/text-to-speech) - Use Case — Image to Video: [deapi.ai/use-cases/image-to-video](https://deapi.ai/use-cases/image-to-video) - Use Case — Video to Text: [deapi.ai/use-cases/video-to-text](https://deapi.ai/use-cases/video-to-text) - Use Case — Music Generation: [deapi.ai/use-cases/music-generation](https://deapi.ai/use-cases/music-generation) - Use Case — AI Video Avatar: [deapi.ai/use-cases/ai-video-avatar](https://deapi.ai/use-cases/ai-video-avatar) - Use Case — AI Image Editor: [deapi.ai/use-cases/ai-image-editor](https://deapi.ai/use-cases/ai-image-editor) - Use Case — Prompt Enhancer: [deapi.ai/use-cases/prompt-enhancer](https://deapi.ai/use-cases/prompt-enhancer) - Use Case — n8n AI Workflows: [deapi.ai/use-cases/n8n-ai-workflows](https://deapi.ai/use-cases/n8n-ai-workflows) - Use Case — Claude Code: [deapi.ai/use-cases/claude-code](https://deapi.ai/use-cases/claude-code) - Use Case — OpenClaw: [deapi.ai/use-cases/openclaw](https://deapi.ai/use-cases/openclaw) - Compare: [deapi.ai/compare](https://deapi.ai/compare) - Compare — deAPI vs. Replicate: [deapi.ai/compare/replicate](https://deapi.ai/compare/replicate) - Compare — deAPI vs. fal: [deapi.ai/compare/fal](https://deapi.ai/compare/fal) - Compare — deAPI vs. Together: [deapi.ai/compare/together](https://deapi.ai/compare/together) - Compare — deAPI vs. OpenAI: [deapi.ai/compare/openai](https://deapi.ai/compare/openai) - Compare — deAPI vs. ElevenLabs: [deapi.ai/compare/elevenlabs](https://deapi.ai/compare/elevenlabs) - Case Study — Humain: [deapi.ai/case-studies/humain](https://deapi.ai/case-studies/humain) - Blog: [deapi.ai/blog](https://deapi.ai/blog) - Pricing: [deapi.ai/pricing](https://deapi.ai/pricing) - Changelog: [deapi.ai/changelog](https://deapi.ai/changelog) - Status Page: [status.deapi.ai](https://status.deapi.ai) - GitHub: [github.com/deapi-ai](https://github.com/deapi-ai) - Python SDK: [github.com/deapi-ai/deapi-python-sdk](https://github.com/deapi-ai/deapi-python-sdk) - MCP Server Source: [github.com/deapi-ai/mcp-server-deapi](https://github.com/deapi-ai/mcp-server-deapi) - Claude Code Skills: [github.com/deapi-ai/claude-code-skills](https://github.com/deapi-ai/claude-code-skills) - n8n Node: [n8n.io/creators/deapi](https://n8n.io/creators/deapi/) - llms.txt: [deapi.ai/llms.txt](https://deapi.ai/llms.txt) - Twitter/X: [x.com/deAPI_](https://x.com/deAPI_) - Discord: [discord.com/invite/UFfK5YRBsr](https://discord.com/invite/UFfK5YRBsr) - Contact Sales: [deapi.ai/contact-sales](https://deapi.ai/contact-sales) - Privacy Policy: [deapi.ai/privacy-policy](https://deapi.ai/privacy-policy) - Terms of Service: [deapi.ai/terms-of-service](https://deapi.ai/terms-of-service)