Agent Quickstart
This page is a single, linear runbook for an autonomous agent (or the code orchestrating one) to drive the Prezent Platform API end to end:
- Discover the surface area.
- Authenticate with a Bearer token.
- Start an async job.
- Track it to a terminal state (poll, stream, or webhook).
- Handle success and failure.
- Back off when rate-limited.
Everything here links back to the page that documents it in full. If you are wiring Prezent into an MCP-aware client (Claude, Cursor, Cline, Continue, Zed), you can skip the HTTP plumbing entirely — see Agents & MCP.
1. Discover
Two machine-readable entry points on the Prezent docs site describe the whole API (paths are relative to this documentation site's origin):
/llms.txt— an llms.txt index: a short summary plus links to every documentation page and the OpenAPI spec. Start here to enumerate what exists./openapi/openapi-v2.yaml— the OpenAPI 3.1 contract for API 2.0 (the current version). Every path, request body, response schema, and error code is defined here. Load it to generate a client or to validate requests before sending them. The 1.0 contract remains at/openapi/openapi.yaml.
A fuller, self-contained digest of the whole contract lives at
/llms-full.txt.
The same contract is browsable interactively at the API Reference.
2. Authenticate
Every endpoint uses API key (Bearer) authentication. Send your key on every request:
Authorization: Bearer YOUR_API_KEY
API keys are issued by your Customer Success Manager (self-service key
generation is not currently supported). See
Getting Started → Authentication
for key scoping, expiry, and the 401 codes you may see.
The canonical production host is https://api.prezent.ai.
3. Start an async job
Most useful operations are asynchronous. You POST to an entry
endpoint and receive a callback_id:
curl -s -X POST https://api.prezent.ai/api/v2/generate \
-H "Authorization: Bearer $PREZENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "prompt": "A 5-slide deck on renewable energy" }'
{ "message": "Job submitted successfully",
"resData": { "callback_id": "cb_123" },
"error": null }
Note the payload is under resData, not data — success shapes vary by
endpoint on this API, so read the schema for the one you are calling.
Make the start idempotent (recommended)
Resource-creating writes (POST/PUT/PATCH) accept an optional
Idempotency-Key request header so a retry after a network error
does not create a duplicate job. Send a unique key (a UUID is ideal)
per logical operation:
curl -s -X POST https://api.prezent.ai/api/v2/generate \
-H "Authorization: Bearer $PREZENT_API_KEY" \
-H "Idempotency-Key: 8e6df756-18f6-4f16-8e12-7d7a5c5cb181" \
-H "Content-Type: application/json" \
-d '{ "prompt": "A 5-slide deck on renewable energy" }'
A retry with the same key and an identical body returns the cached
response verbatim with an Idempotency-Replayed: true header, so the
job is never created twice. See
Developer Guide → Idempotency for
the cache window and the behaviour on body mismatch.
The Template Converter family follows the same shape:
POST /api/v1/template-converter/startreturns acallback_id. See the Template Converter API.
4. Track completion
How you learn a job finished depends on the service:
| Service | Mechanism |
|---|---|
| AutoGenerator | Stream (SSE) — the only mechanism; there is no status endpoint |
| Template Converter | Poll its status endpoint |
| Either | Webhooks — push completion into your own backend |
AutoGenerator — read the stream
Exchange the callback_id for a stream URL, then read events:
curl -s -X POST https://api.prezent.ai/api/v2/streams/sessions \
-H "Authorization: Bearer $PREZENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "callback_id": "cb_123" }'
You receive a short-lived stream_url at data.stream_url. Open it with
any SSE client — no Authorization header, the token is in the URL.
Every event has the same shape, which makes this easy to consume programmatically:
{ "status": "inprogress",
"message": "Analyzing the key elements",
"callback_id": "cb_123" }
Read status until it is no longer inprogress; it then becomes
success, failed, or cancelled and the stream closes. A success
event carries download_url.
message is written for display — surface it to a user verbatim rather
than inventing your own progress copy.
Reconnection, keepalives, and code samples are in Streaming (SSE).
Template Converter — poll
The Template Converter takes its callbackId in the path:
GET /api/v1/template-converter/status/{callbackId}
It returns 200 whenever the job is found — branch on the status field
in the body, not on the HTTP status code. Start at 2–5 seconds with
jittered exponential backoff up to ~30 seconds; do not poll faster than
every 2 seconds.
See Developer Guide → Async operations.
Either — subscribe to webhooks
To avoid holding a connection open, subscribe an HTTPS URL once and
Prezent delivers a signed POST on completion. The relevant event types
are autogeneration.completed / autogeneration.failed and
template_conversion.completed / template_conversion.failed. Verify
the X-Prezent-Signature (HMAC-SHA256) before acting, and deduplicate
on the event id. See Webhooks.
5. Handle terminal states
Whichever mechanism you chose, branch on the terminal state:
-
Success — for AutoGenerator, the stream's
status == "success"(or theautogeneration.completedwebhook). The terminal event carriesdownload_url.cautiondownload_urlmay benullon a generation stream — the deck is built but not yet exported. That is still a success: callPOST /api/v2/autogenerator/downloadand read that stream for the file. Do not treatnullas a failure.For Template Converter,
status == "success"on its status response; use its download endpoint (see the Template Converter API). -
Failure — the stream's
status == "failed"or"cancelled", afailedstatus response, or the*.failedwebhook. On a stream, the reason is inmessage. HTTP-level failures arrive in the standard error envelope; readerror.codeagainst the error catalog to decide whether to retry, fix the input, or surface the error.
6. Back off on rate limits
When you exceed a limit the API returns HTTP 429 with the standard
error envelope. Use both the headers and the body:
X-RateLimit-Remainingis returned on successful responses from rate-limited endpoints — read it to self-throttle before you hit the wall (X-RateLimit-LimitandX-RateLimit-Resetaccompany it).- On a per-category
RATE_LIMIT_EXCEEDED429, honourRetry-After(seconds to wait) — it ships with the sameX-RateLimit-*headers. error.codeon a429isTOO_MANY_REQUESTS(gateway),RATE_LIMIT_EXCEEDED(per-category), orUSAGE_LIMIT_EXCEEDED(annual) — the source of truth for why you were limited. The gateway throttle and the annual quota do not carryX-RateLimit-*/Retry-After, so fall back to backoff there.
Always layer your own jittered exponential backoff (start ~1–2 s, cap
~30 s) on top of Retry-After so a fleet of agents does not retry in
lockstep. The full limit model (gateway throttle, per-minute limits,
annual quotas) is in
Developer Guide → Usage quotas and rate limits.
Putting it together
A robust agent loop, in pseudocode:
spec = GET /openapi/openapi-v2.yaml # on the Prezent docs site
# 1. start (retry a 429 with Retry-After + jitter; the Idempotency-Key
# makes a retry safe — it will not create a second generation)
job = POST /api/v2/generate
(Authorization: Bearer ..., Idempotency-Key: <uuid>)
callback_id = job.resData.callback_id
# 2. mint a stream URL for it
session = POST /api/v2/streams/sessions { callback_id }
stream_url = session.data.stream_url
# 3. read events. No Authorization header — the token is in the URL.
# Set NO read timeout: a :ping arrives every 15s to prove liveness.
download_url = null
for event in SSE(stream_url):
switch event.status:
case "inprogress": report event.message to the user; continue
case "success": download_url = event.download_url; break
case "failed", "cancelled": surface event.message; stop
# on a dropped connection, reconnect with &last_event_id=<last id: seen>;
# if the token expired, mint a fresh URL — it replays the whole turn.
# 4. a null download_url means "not exported yet", not "failed"
if download_url is null:
dl = POST /api/v2/autogenerator/download { callback_id, export_type }
download_url = read the same event loop over dl.stream_url
Where to go next
- Getting Started — first call, response envelopes, status codes.
- Developer Guide — rate limits, error codes, idempotency, pagination, async patterns.
- Agents & MCP — drive all of this as MCP tool calls with no HTTP code.
- Webhooks and Streaming (SSE) — push and real-time completion tracking.
- API Reference — every endpoint, interactively.