Sume SDK idempotency key: idempotencyKey option or header?
subscribeFormatRun takes an idempotencyKey option and generates one for you; generated operations like generateVideoV1 need the idempotency-key header.

With @sume-com/sdk, subscribeFormatRun takes an idempotencyKey option and generates a UUID when you omit it. Generated operations such as generateVideoV1 take the key as a request header instead: headers: { "idempotency-key": ... }.
Mixing them up is easy, and the cost is real: the client retries a POST only when it carries an Idempotency-Key, so a missing key means no automatic retry rather than a duplicate bill.
Where does each helper want the key?
Both snippets come from the SDK docs. subscribeFormatRun documents idempotencyKey (auto UUID, null to send none) and notes a replay of a finished run returns immediately. The generation-job example passes headers: { "idempotency-key": crypto.randomUUID() } to generateVideoV1.
| Call | How to pass the key | If omitted |
|---|---|---|
| subscribeFormatRun | idempotencyKey option | Auto UUID |
| generateVideoV1 and other generated operations | headers: { "idempotency-key": ... } | No key, no automatic POST retry |
| Raw HTTP | Idempotency-Key header | No safe replay |
Should the key be random or derived?
For a one-shot call a random UUID is fine. For work you might replay from your own queue, derive the key from your own record, such as an order id and version, so a restart reuses it. The SDK docs' example uses order-8823-promo-v1.
Reuse a key only for the same operation and payload. The API answers 409 idempotency_conflict when a key is reused for a different one.
Why does a retry need the key?
The client retries 408, 429, 5xx, and transport failures twice by default with exponential backoff and jitter, honoring retry-after. A POST is retried only with an Idempotency-Key, because a replay would otherwise start and bill a second run.
The same rule is behind the docs' advice not to resubmit a paid request just because your local worker timed out.
Generated operations do not throw
They resolve with { data, error, response }, so check error before reading data.
import { createSumeClient, generateVideoV1 } from "@sume-com/sdk";
const client = createSumeClient({ apiKey: process.env.SUME_API_KEY! });
const { data, error } = await generateVideoV1({
client,
headers: { "idempotency-key": "clip-2026-10-02-001" },
body: { prompt: "Slow push-in on a ceramic mug", mode: "async" },
});
if (error) throw new Error(JSON.stringify(error));
console.log(data!.data.request_id);What Sume does not do
The SDK is server-side only: the API key spends your credits and there is no browser-safe variant. Put your own endpoint in front and attach the key there.
Quick checklist
The points above reduce to a short list you can paste into a runbook.
- Pass idempotencyKey to subscribeFormatRun, or accept its generated UUID.
- Pass headers idempotency-key to generated operations.
- Derive the key from your own record when you may replay from a queue.
- Reuse a key only for the same operation and payload.
- Check error before data on generated operations, because they do not throw.
Sources
Related posts
More in Developers
- @sume-com/sdk waitForJob is not exported: a 26-line replacement
The docs show waitForJob, but the npm build of @sume-com/sdk 0.2.0 does not export it. Here is a fetch version with 429 tolerance and a deadline.
- Check an Avatar payload with sume tools schema before --confirm-paid
sume tools schema avatar-videos.create --json prints the exact fields before you pass --confirm-paid. A read-only pre-flight loop for a spending CLI command.
- Cost of one Sume agent thread or turn: /v1/usage thread_id and job_id
Pass thread_id to GET /v1/usage to sum one Studio Agent thread, or a turn's job id as job_id for that turn plus every job it commissioned. Fields and a request.
- Sume /v1/balance: next_expires_at and the expiring-soon fields
GET /v1/balance returns USD micros and cents, a funded or empty state, and an expiration block with the next expiry and the amount expiring soon. Field list.
Written by Sume