{"openapi":"3.1.0","info":{"title":"Reality Fabricator API (agent tools)","version":"2026-10-29","description":"The core of the rfab.ai API for AI agents: web search and page reading, video watching, images, video, speech, sound effects, transcription, chat on 100+ models, research, phone calls. Billed in RFab tokens (50,000 = $1). The full reference (comics, film, music, 3D, dubbing, lip-sync, print, …): https://rfab.ai/.well-known/llms-full.txt. MCP: https://api.rfab.ai/api/mcp (Streamable HTTP, Authorization: Bearer rfab_…). OpenAI-compatible chat with tools: https://api.rfab.ai/api/v1."},"servers":[{"url":"https://api.rfab.ai"}],"components":{"securitySchemes":{"apiKey":{"type":"apiKey","in":"header","name":"X-API-Key","description":"An rfab_… key from https://rfab.ai/settings#api-keys"}}},"paths":{"/api/tools/web-search":{"post":{"operationId":"web_search","summary":"Search the live web; results with title, url, snippet and date.","description":"Searches the live web and returns up to `count` results. About 9,000 tokens ($0.18) a search on Grok live search, 75 tokens when DeepSeek Search is configured. Follow up with read_page on a result to read it whole.","tags":["web"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","description":"What to search for (≤400 characters)."},"count":{"type":"number","description":"How many results, 1-20 (default 8)."}},"required":["query"]}}}}}},"/api/tools/read-page":{"post":{"operationId":"read_page","summary":"Read a web page as clean text with its links (25 tokens).","description":"Fetches a public web page and returns its main text as Markdown-style text (headings, lists, absolute links), with the title. 25 tokens a page. PDFs and DOCX go through the document reader instead.","tags":["web"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"The full http(s) link."},"maxChars":{"type":"number","description":"Most characters to return, ≤200,000 (default 50,000)."}},"required":["url"]}}}}}},"/api/tools/watch-video":{"post":{"operationId":"watch_video","summary":"Watch a video (YouTube or a direct file link) and answer a question about it.","description":"Gemini watches the video and answers. A public YouTube link works as is; anything else must be a direct link to a video file (≤300 MB). Leave the question out for a scene-by-scene description with timestamps. Billed from the model's usage (a short clip ≈ 400-1,100 tokens; longer videos scale with length). `start`/`end` in seconds watch only part; `lowResolution` costs about a third.","tags":["web"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoUrl":{"type":"string","description":"YouTube link or direct video file link."},"question":{"type":"string","description":"What you want to know (optional)."},"start":{"type":"number","description":"Start at this second (optional)."},"end":{"type":"number","description":"Stop at this second (optional)."},"lowResolution":{"type":"boolean","description":"Watch at low resolution, about a third of the cost."}},"required":["videoUrl"]}}}}}},"/api/research":{"post":{"operationId":"research_start","summary":"Start a cited multi-model research report (Grok + Gemini + Perplexity).","description":"Starts a deep research job and returns a jobId. Runs 1-4 minutes; fetch it with research_result. depth 1-6 (default 3); maxCostTokens caps the spend (default 150,000). Needs 20,000 tokens in balance to start.","tags":["web"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"question":{"type":"string","description":"The research question."},"depth":{"type":"number","description":"1 (fast) to 6 (most verification), default 3."},"maxCostTokens":{"type":"number","description":"Spending cap in tokens (default 150,000)."}},"required":["question"]}}}}}},"/api/research/{jobId}":{"get":{"operationId":"research_result","summary":"Get a research job: status, and the cited report when done.","description":"Poll every 10-15 s. When status is completed, result.document is the report and result.sources its sources. Results expire after 2 hours.","tags":["web"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"},"description":"The jobId research_start returned."}]}},"/api/image-generation/generate":{"post":{"operationId":"generate_image","summary":"Make a picture from a prompt (100+ models).","description":"Generates an image. Pass `style` (pixel-art, anime, photorealistic, text-rendering, game-assets, premium, fast, budget, …) to let the API pick the model, or a `modelId` from list_image_models. Do not ask for a quality tier: the model matters, the tier almost never does. Through MCP this waits up to 90 s for the picture; if it is still running you get a jobId for job_status.","tags":["media"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"prompt":{"type":"string","description":"What to draw."},"style":{"type":"string","description":"A style keyword; the API picks the best model for it."},"modelId":{"type":"string","description":"A model id from list_image_models (overrides style)."},"width":{"type":"number","description":"Width in pixels."},"height":{"type":"number","description":"Height in pixels."},"negativePrompt":{"type":"string","description":"What to avoid."},"seed":{"type":"number","description":"Seed for repeatability."}},"required":["prompt"],"additionalProperties":true,"description":"Sent by the MCP server as well: {\"async\":true,\"imageCount\":1,\"saveToGallery\":true}."}}}}}},"/api/image-generation/img2img":{"post":{"operationId":"edit_image","summary":"Change an existing picture with a prompt (restyle, edit, variation).","description":"Image-to-image: give the source picture and say what to change. `strength` 0-1 = how far from the source. Through MCP this waits up to 90 s.","tags":["media"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"imageUrl":{"type":"string","description":"The source picture (URL or data URI)."},"prompt":{"type":"string","description":"What to change."},"modelId":{"type":"string","description":"A model id (optional)."},"strength":{"type":"number","description":"0-1, how far from the source (default model-specific)."},"characterReferenceUrl":{"type":"string","description":"A reference picture of the character to keep consistent (optional)."}},"required":["imageUrl","prompt"],"additionalProperties":true,"description":"Sent by the MCP server as well: {\"async\":true,\"imageCount\":1}."}}}}}},"/api/image-generation/isolate-figure":{"post":{"operationId":"remove_background","summary":"Cut the subject out of a picture; transparent PNG back.","description":"Removes the background (RMBG-2.0) and returns a transparent PNG URL.","tags":["media"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"imageUrl":{"type":"string","description":"The picture."}},"required":["imageUrl"]}}}}}},"/api/image-generation/upscale":{"post":{"operationId":"upscale_image","summary":"Upscale a picture 2x, 3x or 4x.","description":"2,000 / 4,500 / 8,000 tokens for 2x / 3x / 4x.","tags":["media"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"imageUrl":{"type":"string","description":"The picture."},"scale":{"type":"number","description":"2, 3 or 4 (default 2)."}},"required":["imageUrl"]}}}}}},"/api/image-generation/generate-video":{"post":{"operationId":"generate_video","summary":"Animate a picture into a video clip (always async: returns a jobId).","description":"Image-to-video. Leave the model and resolution out (the default, Seedance 2.0 mini at 480p, is the house workhorse: about 3,000 tokens a second). Returns a jobId and estimatedSeconds; check it with job_status after that time. 4-15 s clips (longer picks Seedance 2.5 by itself).","tags":["media"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"imageUrl":{"type":"string","description":"The first frame."},"prompt":{"type":"string","description":"The motion: what happens, how the camera moves."},"duration":{"type":"number","description":"Seconds (default 5)."},"aspect_ratio":{"type":"string","description":"16:9, 9:16 or 1:1."},"videoModelId":{"type":"string","description":"A model id from list_video_models (optional; leave out for the default)."}},"required":["imageUrl","prompt"],"additionalProperties":true}}}}}},"/api/image-generation/job/{jobId}":{"get":{"operationId":"job_status","summary":"Status of an image, video or music job; the result when completed.","description":"status is processing, completed (result carries imageUrl / images / videoUrl / songs) or failed (error says why). Wait until etaAt / estimatedSecondsRemaining before polling again. Jobs expire 2 hours after creation.","tags":["media"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"},"description":"The job id."}]}},"/api/image-generation/models":{"get":{"operationId":"list_image_models","summary":"Every image model with its capabilities, tags and price.","description":"The image model catalog (large). Use a model's id as modelId.","tags":["media"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}}}},"/api/image-generation/i2v-models":{"get":{"operationId":"list_video_models","summary":"Every image-to-video model.","description":"The video model catalog. Use a model's id as videoModelId.","tags":["media"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}}}},"/api/audio/synthesize":{"post":{"operationId":"text_to_speech","summary":"Speak text in a voice; a permanent mp3 URL back.","description":"Up to 5,000 characters. 3 tokens a character on the stock voices. Voices from list_voices; directable voices (gem-…) take a `direction` (\"quiet, slow, grieving\") and inline <sigh> <laugh> <breath>.","tags":["audio"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","description":"What to say."},"voice":{"type":"string","description":"A voice id (default aura-2-thalia-en)."},"direction":{"type":"string","description":"How to say it (directable voices only)."}},"required":["text"],"description":"Sent by the MCP server as well: {\"returnUrl\":true,\"format\":\"mp3\"}."}}}}}},"/api/audio/voices":{"get":{"operationId":"list_voices","summary":"The voice catalog for text_to_speech.","description":"Voices with ids, languages and descriptions. `language` narrows it (es, fr, de, …).","tags":["audio"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"parameters":[{"name":"language","in":"query","required":false,"schema":{"type":"string"},"description":"Two-letter language code (optional)."}]}},"/api/audio/transcribe":{"post":{"operationId":"transcribe_audio","summary":"Speech to text from an audio or video URL; optional speaker labels.","description":"430 tokens a minute of audio. Up to 10 MB. diarize: true labels who said what.","tags":["audio"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"audioUrl":{"type":"string","description":"Link to the audio or video."},"language":{"type":"string","description":"Language code (optional)."},"diarize":{"type":"boolean","description":"Label the speakers."}},"required":["audioUrl"]}}}}}},"/api/tools/sound-effect":{"post":{"operationId":"sound_effect","summary":"Make a sound effect from a description; mp3 URL back.","description":"200 tokens a second (no seconds = billed as 10 s). Up to 30 s. loop: true makes it seamless for looping.","tags":["audio"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","description":"What the sound is."},"seconds":{"type":"number","description":"0.5-30 (optional)."},"loop":{"type":"boolean","description":"Make it loop seamlessly."}},"required":["text"]}}}}}},"/api/chat/completions":{"post":{"operationId":"chat","summary":"One completion from any of 100+ models (including uncensored ones).","description":"model is \"provider:model\" from list_chat_models. Billed from real usage × the model's rate. A provider outage reroutes to the SAME model on another API, never a different one. (For tool calls / an OpenAI SDK, the base URL https://api.rfab.ai/api/v1 is OpenAI-compatible.)","tags":["text"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"model":{"type":"string","description":"\"provider:model\", e.g. \"grok:grok-4.3\"."},"messages":{"type":"array","description":"Chat messages [{ role, content }].","items":{"type":"object","properties":{"role":{"type":"string","description":"system | user | assistant"},"content":{"type":"string","description":"The text."}},"required":["role","content"]}},"systemPrompt":{"type":"string","description":"Optional system prompt."},"maxTokens":{"type":"number","description":"Most output tokens."},"temperature":{"type":"number","description":"0-2."}},"required":["model","messages"]}}}}}},"/api/chat/completions/models":{"get":{"operationId":"list_chat_models","summary":"The chat model catalog with each model's rate.","description":"Every \"provider:model\" id the chat tool takes, with its billing multiplier.","tags":["text"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}}}},"/api/phone-calls":{"post":{"operationId":"phone_call","summary":"Have a voice agent phone someone with a briefing; returns a call id.","description":"Only call people who expect calls from this account (usually its owner). context = the full briefing the voice agent gets (≤24,000 chars; summarize, it is never truncated). Calls run minutes: check phone_call_status until it ends, then read summary, actionItems and transcript.","tags":["phone"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"phoneNumber":{"type":"string","description":"E.164, e.g. +15551234567."},"context":{"type":"string","description":"The briefing: who, what you need from them, the facts."},"purpose":{"type":"string","description":"One-line reason (≤200 chars)."},"agentName":{"type":"string","description":"How the agent introduces itself."},"firstMessage":{"type":"string","description":"Custom opener (10-60 words)."},"maxDurationSeconds":{"type":"number","description":"60-600 (default 600)."},"interruptWords":{"type":"number","description":"Words the person must say to interrupt (1-10, default 2; 4+ in noise)."}},"required":["phoneNumber","context"]}}}}}},"/api/phone-calls/{id}":{"get":{"operationId":"phone_call_status","summary":"A call's status, and its summary, action items and transcript when it ends.","description":"ringing / in-progress are normal for minutes. Read summary + actionItems + transcript once it has ended.","tags":["phone"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The call id."}]}},"/api/tokens/balance":{"get":{"operationId":"token_balance","summary":"The account's token balance (50,000 tokens = $1).","description":"The balance the key spends from.","tags":["account"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Success. JSON with `success: true` and the result fields."},"400":{"description":"The request is wrong; `error` and `code` say how."},"401":{"description":"No or bad API key."},"402":{"description":"Not enough tokens (INSUFFICIENT_TOKENS) or the daily spend limit is reached."},"502":{"description":"The provider failed; nothing billed unless it billed us."}}}}}}