> An installable agent skill for AI Content Drop. Machine-readable copy: > https://aicontentdrop.com/skills/batch-generation-runner/SKILL.md. > Ships with the aicontentdrop package, and is listed in > /skills/index.json.

Running many generations without melting the rate limit

The failure mode this skill prevents: a loop that fires one HTTP request per item, hits the 120-per-minute ceiling a third of the way through, and leaves the user with a half-finished storyboard and no idea which shots exist.

Quote the whole job first, in one call

Never loop the cost endpoint. POST /v1/models/cost prices up to 50 model/quantity pairs together, needs no credential, and reports errors per item so one bad model id does not fail the quote:


curl -sX POST https://aicontentdrop.com/v1/models/cost \
  -H "Content-Type: application/json" \
  -d '{"items":[{"model_id":"kling_3_0","quantity":8},
                {"model_id":"veo_3_fast","quantity":2}]}'

{
  "count": 2,
  "credits_total": 204,
  "items": [
    { "index": 0, "model_id": "kling_3_0",  "credits_each": 22, "quantity": 8,
      "credits_total": 176, "type": "video", "error": null },
    { "index": 1, "model_id": "veo_3_fast", "credits_each": 14, "quantity": 2,
      "credits_total": 28,  "type": "video", "error": null }
  ]
}

Show the user credits_total before you start. A twenty-shot board on a premium model is a materially different decision from the same board on a cheap one, and they can only make that decision before the credits are gone.

Batch the reads

POST /v1/batch takes up to 20 read operations and returns results in the same order. No credential required.


curl -sX POST https://aicontentdrop.com/v1/batch \
  -H "Content-Type: application/json" \
  -d '{"operations":[
        {"id":"video-models","method":"GET","path":"/v1/models?type=video"},
        {"id":"image-models","method":"GET","path":"/v1/models?type=image"},
        {"id":"quote","method":"GET","path":"/v1/models/kling_3_0/cost?quantity=3"}
      ]}'

The envelope is 200 even when an individual operation fails; each result carries its own status and error. So check per item, never just the outer status:


for (const r of body.results) {
  if (r.status !== 200) console.warn(r.id, r.error?.code ?? r.status);
}

Rules worth knowing before you design around it:

Generations: submit and poll, one key each

Generation is asynchronous. You get a 202 with an id, not a finished video.


curl -sX POST https://aicontentdrop.com/v1/generate/video \
  -H "Authorization: Bearer $ACD_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: shot-04-take-1" \
  -d '{"prompt":"…","model":"kling_3_0"}'

Then poll GET /v1/videos/{id} every 5 seconds until status leaves generating. Terminal states are completed, failed, and timeout.

Give every item its own Idempotency-Key derived from the item, not from the attempt — shot-04-take-1, not a fresh UUID per retry. That is what makes the whole run resumable: re-running the loop after a crash returns the existing generation for items already submitted (24-hour retention) instead of paying twice.

A run loop that survives contact with reality


const CONCURRENCY = 4;             // stay well inside 120/min with polling
const inflight = new Map();

for (const shot of shots) {
  while (inflight.size >= CONCURRENCY) await settleOne(inflight);
  const res = await post("/v1/generate/video", shot.body, {
    "Idempotency-Key": `${runId}:${shot.id}`,
  });
  if (res.status === 429) {                       // obey, do not spin
    await sleep(Number(res.headers["retry-after"]) * 1000);
    continue;
  }
  inflight.set(shot.id, res.body.id);
}

Two things that loop gets right and a naive one does not: it bounds concurrency so polling traffic still fits the budget, and it sleeps for exactly Retry-After on a 429 rather than retrying immediately, which extends the window rather than shortening it.

Report honestly at the end

Credits are charged only on success, so the arithmetic a user needs is:

State both. A run that produced 17 of 20 clips cost 17 clips' worth, and the three failures are free to retry.

Full reference: <https://aicontentdrop.com/docs/batch>

---

Install the plugin: https://aicontentdrop.com/plugin · All skills: https://aicontentdrop.com/skills