Video generation API serverless: split acceptance from result collection
A video generation API serverless integration should let each invocation finish while the render continues. Genace’s asynchronous interface already separates creation from observation: POST the generation request, save the returned job_id, and collect its state using later GET requests. Your function does not need to remain alive for the entire render.
The architecture has three durable boundaries: saving acceptance, saving the terminal snapshot, and saving the delivered artifact. Each boundary should survive a process restart without relying on a timer or promise that existed only in memory.
Return a local tracking reference
Your application endpoint can authenticate the customer, reserve a local request, send the authorized generation POST, and save the accepted identifier. It then returns a local tracking reference that the customer can query through your backend. Keep the Genace API key on the server.
Do not return success before the identifier is saved. If persistence fails after the remote POST succeeds, preserve an ambiguous-attempt record and operational alert. An automatic retry of the entire function can otherwise create a second job.
Collect with short invocations
The following Node.js helper performs one existing-job read. It uses wait=0 to avoid holding the request open for a long poll. Its caller should persist the result and schedule another invocation when the job remains active.
async function collectOnce(jobId) {
const response = await fetch(
`https://genace.ai/api/v1/jobs/${encodeURIComponent(jobId)}?wait=0`,
{
headers: { Authorization: `Bearer ${process.env.GENACE_API_KEY}` },
signal: AbortSignal.timeout(15000),
}
);
if (!response.ok) {
return { kind: 'read_error', status: response.status, jobId };
}
const job = await response.json();
return {
kind: ['succeeded', 'failed', 'canceled'].includes(job.state)
? 'terminal' : 'reschedule',
job,
};
}
Choose the client deadline based on your own hosting budget. Immediate reads can still spend time retrieving upstream status, so wait=0 does not mean zero milliseconds of server work. If the invocation budget is shorter, adjust your architecture and deadline rather than assuming the example fits every platform.
Use a real scheduler
Queue delayed messages or run an authenticated scheduled collector over due local records. Do not depend on setTimeout after returning an HTTP response: the runtime may freeze or terminate the process. Save next_action_at before acknowledging the current message.
The repository’s own deployment currently schedules its cron backstop daily in vercel.json. Public polling actively refreshes job state, but you should not promise minute-level unattended collection based on that daily schedule. Your application owns the collection cadence it promises to customers.
There is no customer callback URL handled by the public generation body shown in this implementation. Build your own durable collection worker instead of assuming a webhook subscription exists because the platform also has an upstream provider webhook route.
Verification checklist
End an invocation immediately after accepted-job persistence and verify that a later scheduled invocation resumes it. Repeat after terminal persistence and before artifact delivery. Confirm that every external customer read passes application authorization and that no API key reaches the browser.
Read resuming jobs, SSE progress, and output storage.
Continue with production operations
Where these facts come from
- codebase: src/app/api/v1/video/generations/route.ts
- codebase: src/app/api/v1/jobs/[id]/route.ts
- codebase: src/app/api/cron/poll/route.ts
- codebase: vercel.json
- Editorial keyword hypothesis; search volume not measured