Production Guide: Polling, Webhooks, Retries, and Status Handling for Content Generation APIs
Last updated July 1, 2026
Production pattern
Treat content generation as an asynchronous job: create the request, store the request ID, poll status until completion, register webhooks for callbacks, retry safely, and keep enough metadata to debug every customer-facing asset.
Content generation APIs do real work: importing sources, transcribing media, creating audio, rendering video, generating visuals, and packaging final assets. A production integration should not assume the response body contains the finished result immediately.
AutoContent API follows the normal async pattern. You create a request, receive a request_id, then check /content/Status/{request_id} or receive a webhook when the request progresses. The completion condition to build around is status: 100.
1. Create the Request and Store Metadata
Every production request should carry enough information for your own system to reconcile the result later: user ID, workspace ID, campaign ID, source fingerprint, idempotency key, and where the final asset should be attached.
curl -X POST "https://api.autocontentapi.com/content/Create" \
-H "Authorization: Bearer $AUTOCONTENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"outputType": "audio",
"resources": [
{
"type": "url",
"content": "https://example.com/customer-story"
}
],
"text": "Create a concise two-host discussion for a customer education workflow.",
"callbackData": "workspace=acme;job=content-9842;asset=customer-story-audio"
}'
Persist the returned request_id before doing anything else. Your database row should treat the external request ID as the source of truth for status reconciliation.
2. Poll Until the Request Is Complete
Polling is still useful even when webhooks are enabled. It gives your app a simple recovery path if a callback is delayed, blocked, or missed.
curl -X GET "https://api.autocontentapi.com/content/Status/REQUEST_ID" \
-H "Authorization: Bearer $AUTOCONTENT_API_KEY"
A simple polling loop should:
- Poll on a reasonable interval rather than every second.
- Stop when
statusis100. - Stop and surface an error when the response includes an error state or message.
- Use a timeout that matches the output type. Video and slide decks need more time than short text.
- Write every state transition to your job log.
async function waitForContent(requestId) {
const deadline = Date.now() + 20 * 60 * 1000;
while (Date.now() < deadline) {
const response = await fetch(
`https://api.autocontentapi.com/content/Status/${requestId}`,
{ headers: { Authorization: `Bearer ${process.env.AUTOCONTENT_API_KEY}` } }
);
const body = await response.json();
if (body.status === 100) return body;
if (body.errorMessage || body.errorOn) throw new Error(body.errorMessage || "Generation failed");
await new Promise((resolve) => setTimeout(resolve, 15000));
}
throw new Error("Generation timed out");
}
3. Register Webhooks for Callback Delivery
Webhooks reduce latency and avoid unnecessary polling load. Register a callback URL once, then use callbackData on individual requests so your receiver can route each event.
curl -X POST "https://api.autocontentapi.com/content/Webhook" \
-H "Authorization: Bearer $AUTOCONTENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/api/autocontent/webhook"
}'
Your webhook receiver should be boring and reliable:
- Respond quickly with a 2xx after validating and storing the event.
- Deduplicate by request ID and event timestamp.
- Never trust callback metadata as authorization.
- Queue heavier work such as downloading, processing, or notifying customers.
- Keep polling reconciliation as a backstop.
4. Retry Without Creating Duplicates
Retries are necessary for network failures, timeouts, and temporary API errors. They are also where duplicate assets happen. Use your own idempotency key around the create call: if the same workspace, source hash, output type, and destination already has an active request, return that existing job instead of creating a new one.
Retry rules
- Retry request creation only when the failure is clearly transient or the result is unknown.
- Before retrying, check whether your database already stored a
request_id. - Use exponential backoff with jitter for polling and transient HTTP failures.
- Do not retry requests that failed because the source URL, file, auth, or payload is invalid.
- When retrying after a source changed, store a new source fingerprint.
5. Observe the Whole Lifecycle
A content generation job touches customer data, source retrieval, generation, rendering, delivery, and notifications. Log each phase with the same request ID. At minimum, track:
- Created time, request ID, output type, source count, and callback metadata.
- Polling attempts, webhook events, and final status.
- Failure reason, retry count, and whether the failure is customer-actionable.
- Final asset URL, transcript, share URL, or generated text response.
- Customer-facing notification status.
This matters for every output type, from podcasts to videos. It also matters for teams evaluating a REST API for NotebookLM-style content generation, where predictable status, webhooks, and retries are often the difference between a demo and a production workflow. For official NotebookLM availability context, keep the distinction clear with the NotebookLM API status explainer; for agent tool setup, route readers to the NotebookLM MCP setup guide.
More Articles
Programmatic SEO After AI Overviews: Source-Backed Content Without Scaled Content Abuse
One Source, Seven Assets: Turn a Report into a Podcast, Video, Infographic, Slide Deck, Quiz, Briefing Doc, and Short
Build a Daily AI Briefing Feed from X, Reddit, YouTube, and Deep Research
From Product Feeds to AI Buying Guides: Automating Ecommerce Comparison Content for ChatGPT and Google Shopping
