API documentation
Animate an old portrait into a short, natural video. One call, a photo in, a video out. The pipeline (validation, safety, generation) is the same as on incarn.co: quality is handled for you.
Base URL
https://api.incarn.coAuthentication
Every request is authenticated with a secret key, sent as a Bearer token:
Authorization: Bearer ik_live_xxxxxxxxxxxxxxxxxxxxxxxxCreate and revoke your keys from your dashboard. The full key is shown only once at creation: store it somewhere safe, we only keep a fingerprint and cannot show it to you again. Keep your keys server-side, never in a browser, a mobile app or a public repo.
Credits
Each successful animation uses 1 credit. Your credits come from your subscription (topped up every month) or from packs bought on demand. A failed generation is automatically refunded.
Prepaid model: you only spend what you bought, never a surprise bill. When you run out, the API returns a 402; top up from your dashboard. You can enable auto-recharge (buying a capped pack when your balance drops below a threshold) to never get blocked.
Create an animation
POST /v1/animations
Send the source photo in either of two ways.
A. File (multipart/form-data) — field image, 15 MB max.
curl -X POST https://api.incarn.co/v1/animations \
-H "Authorization: Bearer ik_live_xxx" \
-F "[email protected]" \
-F "prompt=slight smile, small head movement"B. URL (application/json) — field image_url, public http(s) only (private/loopback hosts are rejected).
curl -X POST https://api.incarn.co/v1/animations \
-H "Authorization: Bearer ik_live_xxx" \
-H "Content-Type: application/json" \
-d '{"image_url":"https://example.com/grandmother.jpg","prompt":"slight smile"}'Optional prompt parameter: a free hint about the movement (kept subtle). If both fields are provided, the file wins.
Idempotency — add an Idempotency-Key header to make retries safe: a repeated request with the same key returns the original animation without starting a new generation or spending a credit again.
Response (202/200), processing is asynchronous:
{
"id": "clx...",
"status": "processing",
"video_url": null,
"error": null,
"created_at": "2026-08-10T09:12:00.000Z"
}Track an animation
GET /v1/animations/{id}
Poll this endpoint until status turns to succeeded or failed. Allow 1 to 3 minutes, poll every few seconds.
curl https://api.incarn.co/v1/animations/clx... \
-H "Authorization: Bearer ik_live_xxx"{
"id": "clx...",
"status": "succeeded",
"video_url": "https://cdn.incarn.co/....mp4",
"error": null,
"created_at": "2026-08-10T09:12:00.000Z"
}processing— generation in progress.succeeded— done,video_urlpoints to the MP4.failed— failed,errorexplains, credit refunded.
Webhooks (optional)
Pass a webhook_url at creation to be notified when the job finishes instead of polling. We POST the same body as GET /v1/animations/:id as soon as the job is succeeded or failed.
curl -X POST https://api.incarn.co/v1/animations \
-H "Authorization: Bearer ik_live_xxx" \
-H "Content-Type: application/json" \
-d '{"image_url":"https://example.com/photo.jpg","webhook_url":"https://your-app.com/incarn"}'Each delivery is signed: the X-Incarn-Signature header is sha256=<hmac>, an HMAC-SHA256 of the raw body with your signing secret (shown in your dashboard). Verify it before processing the event.
// Node.js
import { createHmac, timingSafeEqual } from "crypto";
const expected =
"sha256=" + createHmac("sha256", WEBHOOK_SECRET).update(rawBody).digest("hex");
const ok = timingSafeEqual(Buffer.from(expected), Buffer.from(header));Delivery is retried a few times. The body carries the job id: dedupe on receipt if needed.
Limits & errors
Animation creation is limited to 10 requests/minute per account (beyond that: 429). A number of parallel generations also applies, depending on your plan (2, 5 or 15); beyond that: 429, retry when a generation finishes.
400— invalid request (missing photo, too small, or not an image).401— missing or invalid API key.402— out of credits: top up to continue.404— animation not found (unknown id).429— rate or concurrency limit exceeded.
Errors return a JSON body with a message field. The video is generated in full quality (HD). AI labeling and any watermarking policy on redistribution are up to the integrator.
Hosting & data
The application, the database and video storage are hosted in Europe (Germany). Video generation is performed by a non-EU AI partner: the source photos are sent there for processing then deleted. Write to us for your data residency requirements.
Ready to animate?
Create an API key