← Incarn API

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.co

Authentication

Every request is authenticated with a secret key, sent as a Bearer token:

Authorization: Bearer ik_live_xxxxxxxxxxxxxxxxxxxxxxxx

Create 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_url points to the MP4.
  • failed — failed, error explains, 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
API documentation - Incarn