Trigger.dev replay reuses the payload: key the Sume submit from it
A Trigger.dev replay starts a new run with the same payload. Derive the Sume Idempotency-Key from that payload, not a random id, or a replay bills twice.

A replay is a new run, so anything random inside the task changes. If the task derives its Sume Idempotency-Key from the payload, a replay of the same payload returns the original job instead of billing a second one. If it uses a random key, a replay pays again.
Trigger.dev facts are from its Runs docs and v4.6.1 changelog; Sume facts from Communication modes and Errors and credits, read 2026-10-01.
What does Replay do?
The Runs docs say Replay creates a new run with the same payload, using the latest task version. The page does not say what happens to an idempotency key you passed when triggering, so do not rely on one. The v4.6.1 changelog adds CLI commands runs list, runs get, runs replay and runs cancel, so replays can now happen from scripts as well as the dashboard.
Which key survives a replay?
Only a key built from payload fields. Sume treats an exact retry of the same operation and payload under one key as the same job. A different payload under the same key is 409 idempotency_conflict.
| Key source | Replay of same payload | Result |
|---|---|---|
| Payload fields (order id, revision) | Same key | Original Sume job returned |
crypto.randomUUID() in the task | New key | A second paid job |
| Payload fields, edited prompt | Same key, new payload | 409 idempotency_conflict |
How do you write it?
Put a revision number in the payload. Bump it when you truly want a new render, and leave it alone for a retry or replay of the same one. Throw on an API error so Trigger.dev's retry logic sees it.
import { task } from "@trigger.dev/sdk";
import { createSumeClient, generateVideoV1 } from "@sume-com/sdk";
const client = createSumeClient({ apiKey: process.env.SUME_API_KEY! });
export const makeVideo = task({
id: "make-video",
run: async (payload: { orderId: string; prompt: string; revision: number }) => {
const { data, error } = await generateVideoV1({
client,
headers: {
"idempotency-key": "video-" + payload.orderId + "-r" + payload.revision,
},
body: { prompt: payload.prompt, mode: "async" },
});
if (error) throw new Error(JSON.stringify(error));
return { jobId: data!.data.request_id };
},
});What if you want a fresh render on replay?
Then replay is the wrong tool for it. Trigger a new run with a higher revision. A replay uses the latest task version with the old payload, which is for repeating, not for changing.
Sources
Related posts
More in Developers
- Turn a video into a line-art sketch by API with edgedetect
Sume's video filter allowlists edgedetect and negate. Edges come out as white wires on black; negating gives dark lines on white. Modes: wires, colormix, canny.
- Veo 3.1 latency is 11 seconds to 6 minutes: set your poll to match
Google lists Veo 3.1 request latency from 11 seconds to 6 minutes at peak. Poll with a deadline over 6 minutes; Sume's video docs poll every 30 seconds.
- Veo 3.1 videos are stored 2 days: download them, and what Sume does
Google says Veo videos are stored for 2 days, and referencing one for extension resets the timer. Save the file early; Sume jobs return Sume-hosted artifacts.
- AI Gateway async video 413 at 300 KiB: hosted URLs on Sume
AI Gateway caps the persisted video start request at 300 KiB and answers inline base64 with 413. On Sume, send public HTTPS URLs; 413 is payload_too_large.
Written by Sume