In short: create a key in Integrations, call https://autopersonify.com/api/v1 from your server with Authorization: Bearer ap_live_…, and show error.user_message whenever something goes wrong.
How it works
- Sign in to AutoPersonify and, if you want, build your twin in the app (twins can only be made in the app, with a guided, consented recording).
- Go to Integrations → Developer API and create a key. It's shown once — store it as a server secret.
- List presenters or twins, then post a script to
/videos. Poll or use a webhook until it's ready.
Videos use your normal plan minutes and also appear in your Projects, marked as made through the API.
Using Lovable or another AI coding agent
Paste this into Lovable, Cursor, Claude Code or any coding agent. It tells the agent where the docs are, to ask you for the key securely, and how to handle every error. Example: “Every morning, use my twin to summarise each client's PPC review and attach the video to the report.”
Integrate my AutoPersonify account so I can make AI presenter videos (with a stock presenter or my own digital twin) from this app.
1. Read the docs at https://autopersonify.com/developers.md (OpenAPI: https://autopersonify.com/openapi.json).
2. Ask me for my AutoPersonify API key and store it as a server-side secret named AUTOPERSONIFY_API_KEY. Never expose it to the browser.
3. Make all calls from server code to https://autopersonify.com/api/v1 with the header Authorization: Bearer <key>.
4. Build a page where I pick a presenter (GET /presenters, show thumbnail + preview video) or one of my twins (GET /twins, only those with usable_in_videos=true), type or generate a script, and create the video (POST /videos with an idempotency_key).
5. Track status by polling GET /videos/{id} every 10–15 seconds (or via webhook) and show the finished video_url in a player.
6. Handle every error exactly as the docs' error table says — always show error.user_message, and show an Upgrade button linking to error.upgrade_url when error.action is "upgrade".Quick start
# 1. See who can present
curl https://autopersonify.com/api/v1/presenters -H "Authorization: Bearer $AUTOPERSONIFY_API_KEY"
# 2. Make a video (use twin_id instead of presenter_id for your twin)
curl -X POST https://autopersonify.com/api/v1/videos \
-H "Authorization: Bearer $AUTOPERSONIFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"presenter_id":"<id>","script":"Hi Sarah, here is this week in your ads...","idempotency_key":"ppc-2026-09-26-client-42"}'
# 3. Check progress until status is "ready"
curl https://autopersonify.com/api/v1/videos/<video id> -H "Authorization: Bearer $AUTOPERSONIFY_API_KEY"// JavaScript (server only)
const res = await fetch("https://autopersonify.com/api/v1/videos", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.AUTOPERSONIFY_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ twin_id, script, idempotency_key: reportId }),
});
const body = await res.json();
if (!res.ok) throw Object.assign(new Error(body.error.user_message), body.error);# Python
import os, requests
r = requests.post("https://autopersonify.com/api/v1/videos",
headers={"Authorization": f"Bearer {os.environ['AUTOPERSONIFY_API_KEY']}"},
json={"presenter_id": pid, "script": script, "idempotency_key": report_id})
data = r.json()
if not r.ok: print(data["error"]["user_message"])Endpoints
| GET | /me | Account, plan and remaining video seconds |
| GET | /presenters | Presenters available to the API, with thumbnail and preview video |
| GET | /twins | Your twins, and whether each can be used in videos |
| GET | /voices | Your own starred voices |
| POST | /videos | Make a video from a script |
| GET | /videos/{id} | Status, progress, video link or friendly error |
| GET | /videos | Recent videos |
| DELETE | /videos/{id} | Delete a video |
POST /videos fields: script (required, up to 3,000 characters), presenter_id or twin_id, optional voice_id, title, webhook_url and idempotency_key (the same key always returns the same video and is never charged twice). Videos usually take 2–10 minutes. The video_url is a private link valid for one hour — store the video id, not the link.
Errors and what to show people
Every error has code, user_message (written for your end user — show it as it is), action, retryable, and upgrade_url when a plan upgrade is needed. Only retry when retryable is true.
| Code | HTTP | Meaning | What your app should do |
|---|---|---|---|
| invalid_api_key | 401 | The key is missing, mistyped or unknown. | Ask the user for a new key (AutoPersonify → Integrations → Developer API). Don't retry. |
| key_revoked | 401 | The key was revoked. | Ask the user to create a new key. Don't retry. |
| allowance_exceeded | 402 | The account has used its video minutes. | Show user_message and a button to upgrade_url. Don't retry until they upgrade. |
| plan_required | 402 | A paid plan is needed (for example using a free-plan twin in a new video). | Show user_message and link to upgrade_url. |
| twin_not_ready | 409 | The twin is still building. | Tell the user and refresh the picker later. |
| not_found | 404 | Presenter, twin or video doesn't exist (or was deleted). | Refresh the picker list and ask the user to choose again. |
| invalid_request | 400 | Missing or invalid fields; see error.fields. | Fix the request. Show field messages if the user typed them. |
| script_too_long | 400 | Script exceeds the per-video character limit. | Ask the user to shorten or split the script. |
| rate_limited | 429 | More than 60 requests or 10 video creates per minute. | Wait for the Retry-After header, then retry. |
| concurrency_limit | 429 | Too many videos rendering at once. | Wait for one to finish (Retry-After), then retry. |
| daily_limit | 429 | Daily video limit reached. | Tell the user to try again tomorrow. Don't retry today. |
| render_failed | 500 | The video couldn't be made (also appears as video.error when status is failed). | Show user_message. Offer one manual retry; if it fails again suggest contacting support. |
| service_unavailable | 503 | Temporary problem on our side. | Retry with exponential backoff (e.g. 5s, 20s, 60s), at most 3 times, then show user_message. |
If a video fails after it was accepted, GET /videos/{id} returns status: "failed" with error.user_message. Show it, keep the script so the person can retry with one tap, and never loop retries automatically.
Webhooks
Add a webhook address in Integrations to be told when API videos are ready or failed. We send video.ready or video.failed with the video object, signed with X-AutoPersonify-Signature: sha256=… = HMAC-SHA256(secret, timestamp + "." + raw body) and X-AutoPersonify-Timestamp.
Limits and security
- 60 requests a minute per key; 10 new videos a minute; plan-based daily and at-once limits.
- Keys are stored only as a secure fingerprint and shown once. Revoke any key instantly.
- Call only from your server. Never put the key in a web page or mobile app.
- Plans: Free (3 video minutes, no card required), Starter £49, Growth £149, Scale £499 a month.
Start free, no card required
Create your account, make your twin in the app, then connect everything else with one key.
Get your API key