Cookies keep FreeInd working. Optional analytics require your permission; ads for free accounts are served by Google, which shows its own consent message where required. Read our cookie policy.
Build against the same pipeline that powers the dashboard: generate images, video, audio, and text, upload media, track usage, and receive signed webhooks. Every endpoint below has request parameters, response examples, copyable code, and a live request runner.
Base URL https://free.ind.in
Stored in this browser only (localStorage) and sent straight to the API when you use Try it. Nothing is sent to the docs page server. Use a scoped key you can revoke.
Three steps from zero to a finished file. You need a workspace (created with your account) and an API key with the scopes for the endpoints you call.
Create a scoped key
In Dashboard → API keys, pick only the scopes you need. The plaintext key is shown once.
Read the model catalog
Call GET /v1/models with your workspaceId. Copy the model id and note its parameterSchema.
Submit, then poll or subscribe
POST /v1/generations returns 201 immediately. Poll the detail endpoint or wait for a signed webhook.
export FREEIND_API_KEY="fi_live_..."
export WORKSPACE_ID="00000000-0000-4000-8000-000000000000"
export BASE="https://free.ind.in"
# 1 — pick a model and copy its id
curl -s "$BASE/v1/models?workspaceId=$WORKSPACE_ID" \
-H "Authorization: Bearer $FREEIND_API_KEY"
# 2 — submit a generation (201 = queued, not finished)
curl -s -X POST "$BASE/v1/generations" \
-H "Authorization: Bearer $FREEIND_API_KEY" \
-H "Idempotency-Key: hero-image-001" \
-H "Content-Type: application/json" \
-d '{
"workspaceId": "'"$WORKSPACE_ID"'",
"modelId": "<model-id>",
"params": { "mode": "text_to_image", "prompt": "a red fox in fresh snow" }
}'
# 3 — poll until succeeded, or wait for the generation.completed webhook
curl -s "$BASE/v1/generations/<generation-id>/raw?workspaceId=$WORKSPACE_ID" \
-H "Authorization: Bearer $FREEIND_API_KEY"Which endpoint do I need?
| Task | Endpoint | Notes |
|---|---|---|
| Image / video / audio / text | POST /v1/generations | One endpoint, mode in params |
| Edit, fill, animate, try-on | POST /v1/generations | image_to_image / image_to_video |
| Multi-step pipeline | POST /v1/workflows/{id}/runs | free.flow |
| Ad / product video | POST /v1/studio/plans | free.studio |
| Slide deck | POST /v1/slides/decks | free.slides |
| Podcast episode | POST /v1/podcast/episodes | free.podcast |
| Audiobook | POST /v1/audiobooks | free.audiobook |
| Clone a voice | POST /v1/voices | free.speech |
| Moodboard | POST /v1/boards | free.boards |
| Chat completion | POST /v1/chat/completions | OpenAI-compatible |
Every free.* tool is available over the same API. Generation-based tools (reel, edit, fill, animate, thumbnail, try-on) use POST /v1/generations with the matching mode; the pipeline tools below have dedicated endpoints.
Pipeline tools need the generations.* scopes; free.flow and reference templates also need workflows.read / workflows.write. Chat accepts any valid key.
Building with an agent?
Connect Claude, Cursor, VS Code, or OpenCode to the same tools over MCP.
Every request authenticates with a scoped API key created in the dashboard. Send it as a bearer token — never in a query string, never in client-side code.
curl "https://free.ind.in/v1/models?workspaceId=$WORKSPACE_ID" \
-H "Authorization: Bearer $FREEIND_API_KEY"Keys are bound to one workspace. Requests whose workspaceId belongs to a different workspace fail with 403 forbidden.
| Scope | Grants |
|---|---|
| generations.read | Read models, generations, and generation outputs |
| generations.write | Create and cancel generations, and run the generation-based tools |
| workflows.read | Read workflows, runs, and reference analyses |
| workflows.write | Create, edit, and run workflows and reference analyses |
| usage.read | Read usage, credit, and storage reports |
| files.write | Upload files and modify assets |
| assets.read | Read the asset library and download files |
| wallet.read | Read wallet balance and transactions |
| wallet.write | Update wallet settings |
| webhooks.manage | Create, update, and delete webhook endpoints |
| all | Full access (grant sparingly) |
Session endpoints (API keys, billing, workspaces, account) authenticate with the dashboard cookie instead and are marked as such below.
Failures always return a JSON envelope with a stable machine-readable code and the requestId to quote in support requests.
{
"error": {
"code": "validation_error",
"message": "Invalid request body",
"details": [{ "field": "params.prompt", "message": "Required" }],
"requestId": "req_01J9Z8K2"
}
}| Code | HTTP | Meaning |
|---|---|---|
| unauthenticated | 401 | Missing, invalid, expired, or revoked API key. |
| forbidden | 403 | Key is missing the required scope or lacks workspace access. |
| not_found | 404 | The resource does not exist in this workspace. |
| validation_error | 422 | Body or query failed validation; `details[].field` points at the input. |
| idempotency_conflict | 409 | The Idempotency-Key was already used in this workspace. |
| conflict | 409 | The resource is not in a state that allows this action. |
| insufficient_credits | 402 | Not enough plan credits or wallet balance for the job. |
| rate_limited | 429 | Per-key request quota exhausted; retry after X-RateLimit-Reset. |
| model_unavailable | 422 | Model is inactive or does not support the requested mode. |
| upgrade_required | 402 | The feature needs a paid plan. |
| service_unavailable | 503 | A dependency is down; retry with backoff. |
List endpoints accept page (1-indexed) and perPage, and return an items array with pagination metadata:
{
"items": [{ "id": "…" }],
"meta": { "hasNextPage": true, "nextCursor": null, "total": null }
}Keep requesting until hasNextPage is false. Cursor pagination (cursor, nextCursor) is reserved; the credit ledger uses page + limit.
Limits are enforced per API key and come from the workspace plan entitlements (default 60 requests/minute and 1,000/day). Every API-key response carries the current window:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 42A 429 rate_limited response means the window is exhausted. Back off until X-RateLimit-Reset seconds have passed instead of retrying immediately.
Send Idempotency-Key (8–128 chars of [A-Za-z0-9._:-]) on POST requests so a retry after a timeout cannot create a duplicate job. Keys are scoped to the workspace; reusing one returns 409 idempotency_conflict instead of charging twice.
curl -X POST "https://free.ind.in/v1/generations" \
-H "Authorization: Bearer $FREEIND_API_KEY" \
-H "Idempotency-Key: order-1042-scene-3" \
-H "Content-Type: application/json" \
-d @generation.jsonEach delivery is a POST with an X-FreeInd-Signature header shaped t=<unix>,v1=<hex>. Verify HMAC-SHA256 over t + "." + rawBody using the secret returned at creation, then reject anything older than five minutes.
import { createHmac, timingSafeEqual } from 'node:crypto';
// header: "t=1761307218,v1=8f2c..."
export function verifyFreeIndSignature(secret, rawBody, header) {
const [timestampPart, signaturePart] = header.split(',');
const timestamp = timestampPart.slice(2);
const signature = signaturePart.slice(3);
const expected = createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
const valid = timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) < 300;
return valid && fresh;
}Event types: generation.completed, generation.failed, generation.cancelled, generation.expired, workflow.completed, workflow.failed, workflow.cancelled. Deliveries retry with backoff; inspect them with the deliveries endpoint.
Import the collection to get every API-key endpoint with folders, variables, request examples, and response tests that chain a created generation id into the follow-up requests.
Import in Postman:
https://free.ind.in/downloads/freeind-api.postman_collection.json (or drop the downloaded file).apiKey, workspaceId, and modelId.| Variable | Used for |
|---|---|
| baseUrl | API origin (https://free.ind.in) |
| apiKey | Bearer token for every request |
| workspaceId | Workspace path/query parameter |
| modelId | Model to generate with |
| generationId | Captured automatically after create |
| assetId | Captured automatically after upload |
| webhookId | Webhook endpoint id |
A hand-curated OpenAPI 3.1 document powers this page. Point Swagger UI, Insomnia, Stoplight, or an LLM at it directly:
https://free.ind.in/api/docs/json — the raw spec emitted by the live Fastify server (route inventory, no examples).The API is versioned under /v1. Breaking changes ship with a 90-day deprecation window — see the changelog policy.
Unauthenticated endpoints for service health, plans, and the public model catalog. Safe to call from the browser or a startup probe.
Plan-aware model discovery. Always read the catalog before submitting a generation — it carries the credit price and the per-model `parameterSchema` used to validate params.
Create and track generation jobs. Submission is asynchronous: a 201 means the job is queued, not finished. Poll the detail endpoint or subscribe to webhooks for terminal states.
Two ways to feed media into a generation: upload it (private, stored on the platform) or pass a direct http(s)/base64 URL. Uploads use presigned PUT URLs so file bytes never touch the API.
Report on consumption and credit balances. Usage records are written when a generation settles, so totals lag terminal states by seconds.
Pay-as-you-go wallet. Deposit once, then generate at live model prices. Top-ups require a dashboard session; reads and threshold updates work with an API key.
Subscribe to terminal generation and workflow events. Deliveries are signed with HMAC-SHA256 in the `X-FreeInd-Signature` header and retried with backoff.
Key, billing, workspace, and account management. These endpoints authenticate with the dashboard session cookie rather than an API key, and are not part of the Postman collection.
Build, activate, and run multi-step pipelines. A workflow is a DAG of generation nodes with typed flow inputs; a run walks the nodes in order and passes outputs downstream. Pipelines can be one-shot or reusable templates.
Turn a reference image or video into a reusable workflow: analyze its look, structure, and audio feel, then adopt the generated template. Analyses are metered on vision tokens and cached by asset bytes.
Turn a brief into a designed deck: the planner writes an outline and one image generation runs per slide. Export to PPTX or PDF when every slide is ready.
Write a multi-speaker script, render each turn with a different voice, and mix the episode with an optional music bed and outro. Rendering runs on free.flow under the hood.
Turn long text into a single narrated audiobook. The text is chunked, each chunk is rendered with the chosen voice model, and the final mix is assembled on demand.
Clone a voice from uploaded samples, then pass the returned `providerVoiceId` as the `voice` param on any text-to-audio generation. Cloning needs a paid plan and explicit consent.
The ad/studio pipeline: a brief becomes a storyboard of shots, the storyboard runs as a workflow, and captions come back as SRT. Effects and transitions are catalogued for the UI.
Collect assets into ordered boards for review and iteration. Items reference assets; resolve previews with `GET /v1/assets?assetIds=…`. Paid plans only.
Saved generator setups: a mode, an optional model, and the raw form params. Re-apply a preset by sending its params to `POST /v1/generations`.
Group generations and assets into projects for the library. Filter generations and assets by `projectId` once assigned.
Send chat completions with an API key using the OpenAI wire format. Models and quota are exposed alongside, so SDKs can point at this base URL unchanged.
Generate names, taglines, and a colour palette before rendering logo marks with an image model.
Ready to build?
Create a scoped key, grab the Postman collection, and follow the quickstart.