blog/guides·Sep 11, 2026·6 min·by the eroq team

Choosing an AI video API — async jobs, webhooks and refunds

What to check in an AI video API before you build — async jobs, webhook signatures, refunds on failure, billing units, rate limits, MCP and CLI.


Picking an AI video API is not like picking an image API. A video render takes minutes, not seconds, which means the shape of the integration — not the quality of the frames — determines how much of your week it costs. Get the job model wrong and you will be rewriting your queue, your retries and your billing reconciliation later. Here are the seven things to check before you write the first request, with eroq's shapes as the worked example.

1. Async jobs, not a blocking call

A blocking HTTP request that waits for a video is a trap dressed as convenience. Load balancers, serverless platforms and CDNs all have request ceilings well under a long render, so a blocking API works in testing and dies in production at exactly the moment a render takes longer than usual.

The right shape is a job. On eroq, POST /v1/videos/generations returns a job id immediately; you then poll GET /v1/videos/generations/{id} or wait for a webhook. Full reference on /docs/video.

# 1. submit
curl -X POST https://eroq.ai/v1/videos/generations \
  -H "Authorization: Bearer $EROQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "seedance-1-lite",
    "prompt": "A courier weaves a bicycle between stopped cars on a wet avenue at dusk, headlights smearing across the frame. Tracking shot, 35mm film, anamorphic lens, neon noir palette, dynamic tempo.",
    "seconds": 5,
    "aspect": "9:16"
  }'

# 2. poll (or skip this and use a webhook)
curl https://eroq.ai/v1/videos/generations/JOB_ID \
  -H "Authorization: Bearer $EROQ_API_KEY"

What to check elsewhere: whether the video endpoint is genuinely async, and whether there is a list endpoint for recovering jobs after a process restart. If the only record of a render is the response you lost, you will lose renders.

2. Webhooks you can actually verify

Polling is fine to start with and wasteful at volume. A webhook should arrive signed, and the signature scheme should be one you have implemented before.

eroq emits video.generation.succeeded and video.generation.failed with a Stripe-style signature header, and the payload carries a CDN URL rather than inlined base64 — which matters, because a multi-megabyte JSON body will eventually break something in your stack.

Three questions for any vendor: is the payload signed, is there a replay window in the signed material, and does the body carry a URL or the bytes? Verify their answers in their docs, as of September 2026.

3. What happens when a render fails

This is the criterion that separates a real platform from a wrapper, and it is almost never on the pricing page. Ask three things:

Are failures refunded? On eroq, failed generations refund automatically. You reconcile successes, not attempts.

Are policy refusals charged? A blocked request returns content_blocked and is never charged. At scale, a platform that bills refusals is charging you for its own filter.

Is the check before or after the debit? A model your plan does not include returns 403 plan_required before any credits move; an engine without provisioned capacity returns 503 model_unavailable, also before the debit. No silent fallback to a different engine, either — if you asked for a specific model and it is unavailable, you get an error, not a surprise renderer. Silent fallback is the worst failure mode in this category, because your output changes and your logs do not.

4. The billing unit

Two models dominate: per-second metering, and flat credits per clip at fixed anchors. Flat anchors are easier to budget and easier to explain to a finance team; per-second is fairer on odd durations. Neither is wrong, but you need to know which one you are on before you promise a customer a price.

eroq bills credits at per-engine anchors — 60 credits for 5 seconds on Seedance 1.0 Lite, 100 on Motion One, 120 on Kling 2.5 Turbo, 256 for Veo 3 Fast's fixed 8 seconds, and so on across the roster at /models. One credit is about a cent at the entry pack. Credits never expire, and a workspace holds one shared wallet across its seats and keys, which is what makes per-customer accounting your job rather than a pile of separate billing relationships. If you are reselling generation, the mechanics of passing metered costs through are in credit pricing for AI APIs.

5. Rate limits that scale with the plan

Per-key limits on eroq start at 60 requests per minute for chat, 20 for images, 6 for video and speech, multiplied by the plan — Creator doubles them, Studio quadruples them. Key counts scale the same way: 10 keys on Hobby, 20 on Creator, 50 on Studio, 100 on Team, 200 on Agency, with seats to match.

The practical advice is to issue one key per environment and one per customer-facing surface, so a runaway loop in staging throttles staging. Check what any vendor's limits are per key versus per account, because the two produce very different blast radii.

6. Discovery, so you don't hardcode the roster

Rosters change. Hardcode engine ids and prices in your app and you will ship a stale menu.

GET /v1/engines returns each engine with its plan gate, availability and capabilities — whether it supports a seed, an end frame, a negative prompt, audio — and GET /v1/models returns the full model list with prices. Build your UI from those two responses and new engines appear on their own. The spec is machine-readable at /openapi.json, and there is an /llms.txt for coding agents.

7. Agent surfaces — MCP and CLI

Increasingly the thing calling your video API is not your app, it is an agent. Two surfaces worth having:

A remote MCP server. eroq's is at https://eroq.ai/mcp over Streamable HTTP, authenticated with the same Bearer key, exposing generate_image, generate_video, get_video_status, generate_speech, enhance_prompt, list_models, list_voices, list_characters and get_account. It connects to ChatGPT as a custom connector, to Claude on web and desktop, to Cursor and to Codex CLI. For clients that cannot send headers there is a /mcp/<key> form, where the URL is the secret and should be treated like one. Setup per client on /docs/mcp.

claude mcp add --transport http eroq https://eroq.ai/mcp \
  --header "Authorization: Bearer $EROQ_API_KEY"

A CLI. The eroq package runs on Node 18+ with zero dependencies — eroq login, eroq image "…", eroq video "…" -s 8 --aspect 9:16, eroq speech "…" -v aria. eroq mcp starts a local stdio MCP server that writes media to files, which is the shape coding agents actually want.

Two more things, once you're past the basics

Batch structure. If you are rendering sequences rather than one-offs, look for a resource that models the sequence. eroq's films resource stores a storyboard, and POST /v1/films/{id}/render shoots every scene, billing per scene and stopping cleanly when a wallet runs dry — see /docs/films.

Hosting the output. Rendered URLs are not permanent storage. Either copy them into your own bucket on the success webhook, or use the eroq Store at /v1/storage/objects (2 credits per 10 MB) and keep one system of record.

The checklist

  1. Async job with a list endpoint for recovery.
  2. Signed webhooks carrying URLs, not bytes.
  3. Automatic refunds on failure, and no charge for policy refusals.
  4. Gate checks before the debit, and no silent engine fallback.
  5. A billing unit you can quote to a customer.
  6. Per-key rate limits that scale with the plan.
  7. Runtime discovery of models, prices and capabilities.

Run that list against any vendor, including this one. Everything above is documented at /docs, and priced at /pricing.

FAQ

Is the eroq video API synchronous or asynchronous?

Asynchronous. POST /v1/videos/generations returns a job id, and you either poll the job or receive a signed video.generation.succeeded webhook. A list endpoint returns the workspace's recent jobs so a restart never loses a render.

Do I get charged when a video render fails?

No. Failed generations refund automatically, and requests blocked by the content policy return content_blocked without a charge. Plan gates and unavailable engines are checked before any credits move.

Can I call the video API from an agent instead of code?

Yes — a remote MCP server at https://eroq.ai/mcp exposes generation, status and account tools to ChatGPT, Claude, Cursor and Codex, and the eroq CLI ships a local stdio MCP server that saves renders as files.

Get an API key and submit the first job — /signup.

Tagsapiwebhooksasync-jobsdevelopers

Make this with the models behind the post — start with 50 free credits , or browse every engine and its price .