Three on-ramps. One credit wallet.
Ounie accounts hit the REST endpoints with a bearer key. AI assistants — including the Ounie AI Team — connect over MCP and get a native tool surface. One-off scripts can skip the account and pay for a single hero frame in USDC via x402. All three drive the same pipeline, and account calls draw your shared Ounie credits (1 credit = 1¢) — refused when short, never overdrawn.
An ad runs a pipeline: a frame (an AI actor holding your product, composed into one 9:16 still), a voice (your script spoken by a chosen voice in any of 20 languages via ElevenLabs), a video (the frame lip-synced to that voice), and optional captions burned into the MP4. In auto mode it runs end-to-end; in preview mode it stops at the frame so you can approve it before spending on the voice + video.
Scripts can optionally be grounded in up to 3 of your Ounie brains — facts from your own knowledge base folded into the words the actor says. Grounding is free and needs an ounie.com credential (session cookie or the master key); it's excluded on x402 because a keyless caller has no Ounie account.
Base URL https://aiactors.ounie.com · JSON everywhere · scripts up to 500 characters · the clip length = the spoken length of your script · max 5 ads in flight per account. Finished videos are stored on permanent public URLs.
The dashboard's own auth. Every REST endpoint accepts it, and cookie calls can ground in your brains.
aia_live_…Minted at Dashboard → API keys (shown once, up to 5 active). Send it as Authorization: Bearer aia_live_… or, where headers can't be set, as ?api_key=aia_live_…. It generates and bills normally but has no ounie.com credential, so it cannot ground scripts in brains.
ounie_live_…One key across the whole Ounie app fleet. Enable "Use across Ounie apps" on the key at ounie.com → Settings → API keys and it works here as a Bearer too — and because it IS an ounie.com credential, it unlocks brain-grounded scripts for agents.
Each pipeline step reserves its price from the caller's shared Ounie wallet — the frame (40 cr), then the video (fast 15 cr/s, premium 22 cr/s). Delivery settles it; a failed or aborted step refunds automatically and in full — exactly once, however many pollers race. Because each step is billed separately, a delivered frame stays spent while a failed video refunds on its own (a 10-second premium ad ≈ 262 cr).
If the wallet can't cover a reserve, the call is refused up front with 402 insufficient_credits and a buy_credits_url (https://ounie.com/dashboard/settings) — an agent on your key can never overdraw you.
Free by design: GET reads, downloads, share pages, image uploads, and brain retrieval.
/api/ads— Create an ad{
"actor_id": "maya", // from GET /api/actors …
"actor_image_key": "…", // … OR your upload (POST /api/media/upload?kind=actor)
"product_image_key": "…", // required (POST /api/media/upload?kind=product)
"product_name": "Glow Serum",
"script": "Stop scrolling — …", // spoken words … OR:
"generate_script": true, // let the app write it (+2 cr)
"brain_ids": ["…"], // ground a generated script (≤ 3)
"tier": "video_premium", // video_fast | video_premium
"duration_sec": 10, // 4–15
"auto_advance": true // render frame then video (agents); false = stop at frame
}Auto mode reserves frame + video up front and renders both — poll the ad. Preview mode reserves only the frame and returns it for approval (then call /animate).
/api/ads— List adsQuery params: status, limit, offset. Free.
/api/ads/:id— Poll one adLazily advances a rendering step — each call can settle, refund, or advance the pipeline. This is how agents wait on the video. Free.
/api/ads/:id/animate— Animate an approved frame{ "tier": "video_premium", "duration_sec": 10 }Preview-mode step 2 — reserves the video and starts the render. Only from frame_ready.
/api/ads/:id/reframe— Re-render the frameComposes a fresh hero frame (40 cr), keeping the ad. Only from frame_ready.
/api/ads/:id/abort— Abort a running adRefunds every live step in full and marks the ad aborted. Free.
/api/ads/:id/share— Toggle the share page{ "public": true }Succeeded ads only. Returns share_url (/a/:id). Default private. Free.
/api/ads/:id— Delete an adTerminal ads only (abort a running one first). Free.
/api/media/upload?kind=actor|product— Upload an actor or product imageMultipart "file" or JSON {"url":"https://…"} — up to 10 MB, sniffed server-side, stored private. Returns an image_key. Free.
/api/script— Write a script{ "product_name": "…", "product_description": "…", "brain_ids": ["…"], "topic": "…", "duration_sec": 10 }Generates a hook + spoken words + scene direction (2 cr). Pass the result to /api/ads as "script" to avoid re-billing.
/api/actors— The actor libraryPublic — the curated AI actors (id, name, tags, portrait_url) you can cast. No auth.
/api/brains— List your brainsFor grounding a script. Cookie or master-key callers get their brains; a aia_live_ key gets an honest empty list. Free.
/api/credits— Credit balanceSpendable credits + monthly included remaining + buy_credits url. Free.
/api/pricing— The price listPublic — script/frame/video prices + the x402 endpoint. No auth.
Endpoint https://aiactors.ounie.com/api/mcp (legacy SSE: /api/sse) Header Authorization: Bearer aia_live_… (or ounie_live_…) # Clients that can't set headers append the key to the URL — # this is how the Ounie AI Team connects: https://aiactors.ounie.com/api/mcp?api_key=aia_live_…
| Tool | What it does | Cost |
|---|---|---|
| create_ad | Cast an actor + product + script → renders the hero frame then the spoken video (auto mode). Poll get_ad until succeeded. | frame 40 + video (15–22/s) |
| animate_ad | Preview-mode step 2: animate an approved frame into the spoken video. | video (reserved) |
| get_ad | Poll an ad; advances a rendering step and settles or refunds when it finishes. | free |
| list_ads | List your ads, filterable by status. | free |
| list_actors | The curated AI-actor library. No auth required. | public |
| list_voices | The curated voice catalog. No auth required. | public |
| list_languages | Supported spoken languages + caption styles. No auth required. | public |
| generate_script | Write a UGC script from a product description, optionally grounded in your brains. | 2 credits |
| list_brains | Your Ounie brains for grounding a script (master ounie_live_ key only). | free |
| get_credit_balance | Spendable Ounie credits in the shared wallet. | free |
| get_pricing | The credit prices + the x402 endpoint. No auth required. | public |
| whoami | The authenticated key's owner and key id. | free |
Grounding a script over MCP needs the master ounie_live_ key — it's forwarded upstream to read your brains. A aia_live_ app key creates ads normally but writes ungrounded scripts (and list_brains tells it why).
# 1 — ask; the server answers with payment terms
curl -X POST https://aiactors.ounie.com/api/x402/frame \
-H "Content-Type: application/json" \
-d '{"actor_id":"maya","product_image_url":"https://…/product.png","product_name":"Glow Serum"}'
# → 402 { "x402Version": 1, "accepts": [{ "maxAmountRequired", "payTo", "asset", … }] }
# 2 — sign the terms with your wallet and retry
curl -X POST https://aiactors.ounie.com/api/x402/frame \
-H "Content-Type: application/json" \
-H "X-Payment: <signed payload>" \
-d '{"actor_id":"maya","product_image_url":"https://…/product.png","product_name":"Glow Serum"}'
# → 200 { "frame_url": "https://…/frame.png", "tx_hash": "0x…" }| Endpoint | What | Price |
|---|---|---|
| POST /api/x402/frame | Compose one 9:16 hero frame from a public actor + product image URL | 500000 atomic USDC (≈ $0.50) |
Plainly: x402 is the frame only, and brain-grounded scripts are excluded — an x402 caller has no Ounie account and no brains to ground in. The video needs an account because a multi-minute render outlives an x402 response; the reserve → settle → poll lifecycle exists for exactly that.
{ "error": "code", … }. A charged-then-failed step always refunds.| Code | Status | Meaning |
|---|---|---|
| unauthorized | 401 | Missing or invalid credential — send a session cookie, a aia_live_ Bearer, or ?api_key=. |
| insufficient_credits | 402 | The wallet can't cover the reserve. The body includes required_credits, balance_credits, and buy_credits_url. Nothing was charged. |
| actor_required / product_image_required / script_required | 400 | A create_ad call needs an actor (id or image), a product image, and a script (or generate_script=true). |
| unknown_actor | 400 | actor_id isn't in the library — call list_actors. |
| content_blocked | 400 | The script or product copy failed content screening. Not charged. |
| not_ready_to_animate | 400 | animate_ad was called on an ad that isn't at frame_ready. |
| too_many_running | 429 | You already have 5 ads in flight — wait for one to finish or abort one. |
| not_found | 404 | No ad with that id belongs to this account. |
| service_unavailable | 503 | Generation isn't configured on this deployment. |
| generation_failed | 502 | The provider refused or failed a step. Reserved credits for that step were refunded. |
{ "ad": … }.{
"id": "9f2c…",
"status": "succeeded", // frame_rendering | frame_ready | video_rendering
// | succeeded | failed | aborted
"actor": { "id": "maya", "label": "Maya", "uploaded": false },
"product": { "name": "Glow Serum", "description": "…" },
"script": {
"source": "generated", // user | generated
"hook": "Stop scrolling.",
"text": "Stop scrolling — this changed my mornings.",
"scene_direction": "Holds the bottle to camera, smiles."
},
"grounded": true,
"grounding_thin": false, // true = brains had nothing relevant
"brain_ids": ["…"],
"tier": "video_premium",
"duration_sec": 10,
"aspect_ratio": "9:16",
"frame_url": "https://…/frame.png",
"video_url": "https://…/video.mp4", // null until the video succeeds
"error": null,
"is_public": false, // share page off by default
"source": "api", // web | api | mcp | x402
"created_at": "2026-07-13T…",
"completed_at": "2026-07-13T…"
}