One key, one balance, every service. Outputs come back as artifacts you can pass straight into the next call.
Sign in with your 4i account to create a key.
One paste with everything a coding agent (Claude Code, Cursor, Copilot…) needs: base URL, a key placeholder, endpoints, response shapes and error rules. The agent reads the current services from GET /services.
# 4i Platform API — integration brief
Use this to integrate the 4i Platform API: one REST API for image, video, audio and text AI services. Outputs are artifacts whose ids can be passed straight into the next service.
## Configuration
- Base URL: https://platform.4i.app/api/v1
- API key: <YOUR_4I_API_KEY>
- Auth header on every call (except GET /services): `Authorization: Bearer <YOUR_4I_API_KEY>`
- Store the key as a server-side secret/env var (e.g. `FOURI_API_KEY`). It acts as the account and spends its credits — never ship it to a browser or commit it.
- The key is not included here: ask the developer for it (they get it at the API page of platform.4i.app).
- JSON in, JSON out. CORS is open (`*`).
## Endpoints
- `GET /services` — catalog (no key). Filters: `?output=image|video|audio|text`, `?provider=`, `?censorship=none|low|medium|high|unknown` (unknown = not confirmed yet) (comma lists).
- `POST /run` — run one service. Body: `{ "service": "<id>", "input": { "prompt": "…", "image": "img_…" | "https://…", "video": …, "audio": …, "text": … }, "params": { … }, "session": "ses_…" (optional) }`
- `GET /runs/{id}` — a run and its outputs. Reading it advances a running async run.
- `GET /runs?service=&limit=` — recent runs.
- `POST /uploads` — multipart field `file` (image, video, audio, text; 50 MB max) → artifact `{ "id": "img_…", "kind": "image", "url": "https://…" }`.
- `GET /artifacts/{id}` — an artifact's `url` (media) or `text`.
- `GET|POST /sessions`, `GET|PATCH|DELETE /sessions/{id}` — group runs into threads (optional).
- `GET /me` — the key's account and credit balance.
## Choosing a service
The catalog changes often, so it is not listed here. Call `GET https://platform.4i.app/api/v1/services` (no key needed) to see what is available, and look services up from it rather than hard-coding a list. Each entry in `services` has:
- `id` (pass it as `service`), `name`, `provider` (model maker), `task`, `output` (image|video|audio|text), `async`
- `prompt`: `required` | `optional` | `none`; `slots`: media inputs `[{ "kind": "image"|"video"|"audio"|"text", "required": true|false }]`; `requiresAny`: at least one of these inputs must be sent
- `params`: `[{ "name", "type", "options", "min", "max", "default" }]`
- `price` credits per `unit`, `censorship` (content filter level), `avgMs` (typical run time, or null)
## Run object
```json
{ "id": "run_…", "object": "run", "status": "running|succeeded|failed", "service": "<id>",
"input": { … }, "params": { … },
"outputs": [{ "id": "img_…", "kind": "image", "url": "https://…" }],
"artifact_id": "img_…", "estimate": 0.02, "cost": 0.02, "error": null,
"created_at": "…", "finished_at": "…", "duration_ms": 4210, "balance": 12.5 }
```
Text outputs are artifacts too (`txt_…`); fetch `GET /artifacts/{id}` for the text, or pass the id on as `input.text`.
## Rules to code against
- Inputs: `prompt` is a string; `image`/`video`/`audio`/`text` are an artifact id you own (`img_…`, `vid_…`, `aud_…`, `txt_…`) or a public https URL. Only send the inputs the service's catalog entry lists.
- Params outside a service's list are ignored; omitted params use their defaults.
- Async services (video) answer `"status": "running"`. Poll `GET /runs/{id}` every 5–10 s until `succeeded` or `failed`. Every run has a deadline (usually 10 min, longer for some video models); past it the run is failed and refunded.
- Billing: the estimate is reserved when a run starts and settled to the real cost when it ends. Failed runs are fully refunded.
- A provider/model failure is NOT an HTTP error: you get HTTP 200 with `"status": "failed"` and a human-readable `error`. Always check `status`.
- HTTP errors (`{ "statusMessage": "…" }`): 400 bad input, 401 missing/invalid key, 402 not enough credits (top up at https://platform.4i.app/?buy=credits), 404 unknown service/run/artifact, 429 rate limited (back off and retry).
- Output URLs are public https links; download/copy them if you need them long-term.
## Example
```bash
curl https://platform.4i.app/api/v1/services?output=image
curl https://platform.4i.app/api/v1/run \
-H "Authorization: Bearer <YOUR_4I_API_KEY>" -H "Content-Type: application/json" \
-d '{ "service": "prunaai/p-image", "input": { "prompt": "studio photo of a cream leather sneaker" }, "params": { "aspect_ratio": "1:1" } }'
```
Base URL https://platform.4i.app/api/v1. Send Authorization: Bearer 4i_… on every call. Prices are in credits, reserved when a run starts and settled to the real cost when it ends; failed runs are refunded.
curl https://platform.4i.app/api/v1/run -H "Authorization: Bearer $FOURI_KEY" \
-H "Content-Type: application/json" \
-d '{ "service": "prunaai/p-image",
"input": { "prompt": "studio photo of a cream leather sneaker" },
"params": { "aspect_ratio": "1:1" } }'
→ { "id": "run_…", "status": "succeeded", "artifact_id": "img_…",
"outputs": [{ "id": "img_…", "kind": "image", "url": "https://…" }], "cost": 0.01 }curl https://platform.4i.app/api/v1/run -H "Authorization: Bearer $FOURI_KEY" \
-H "Content-Type: application/json" \
-d '{ "service": "bria/remove-background", "input": { "image": "img_…" } }'curl https://platform.4i.app/api/v1/uploads -H "Authorization: Bearer $FOURI_KEY" -F file=@photo.jpg
→ { "id": "img_…", "kind": "image", "url": "https://…" } Inputs: prompt plus any of image, video, audio, text — each an artifact id you own (img_…) or a public https URL. Each service lists its inputs and params in the catalog and in GET /api/v1/services.