Developer Guide
This guide collects the cross-cutting topics that apply to every Prezent Platform API endpoint — rate limits, the error catalog, async operations, and the response headers you should expect.
For the full interactive endpoint reference, see the API Reference. For first-call walkthroughs, see Getting Started.
What you'll find here
- Overview of Prezent APIs
- Authentication recap
- Response envelopes
- Rate limits
- Error codes
- Async operations
- Idempotency
- Pagination
- Best practices
- Where to go next
Overview of Prezent APIs
| API | Description |
|---|---|
| AutoGenerator | Generate Prezent-quality decks from natural-language prompts, files, and assets; revise them conversationally; download the result. Streaming — progress and results arrive as Server-Sent Events. |
| Template Converter | Apply a target brand template to an uploaded deck. Async with a status endpoint for polling, plus smart-edit endpoints (work-area, layout, modify-format, review suggestions). |
| Audiences | List and search audience profiles configured for your company. |
| Themes | List the presentation themes (brand templates) configured for your company. |
| File Upload | Upload (single + chunked) and validate supporting files before AutoGenerator / Template Converter jobs. |
| File Access | Mint short-lived access tokens for your stored files. |
| Health | Liveness and component health-check endpoints. |
| SCIM — User Management | RFC 7644 (SCIM 2.0) user provisioning. Documented separately. |
Authentication recap
All endpoints (except SCIM, which is documented separately) use a single Bearer token:
Authorization: Bearer YOUR_API_KEY
See Getting Started → Authentication for the full details, or Authentication & Security for the complete security model (key scoping, transport security, and webhook payload integrity across every surface).
Response envelopes
Errors are uniform across every endpoint. Success shapes are not — read the response schema for the endpoint you are calling rather than assuming a shared shape.
Success — canonical envelope (most endpoints)
{
"success": true,
"data": { "...endpoint-specific payload..." }
}
Success — the exceptions. On the AutoGenerator surface,
POST /api/v2/generate and /api/v2/autogenerator/edit return
{ message, resData, error } with the payload under resData;
/api/v2/autogenerator/download returns flat top-level fields; and
GET /api/v2/autogenerator/languages returns { status, message, data }.
The Template Converter has its own exceptions. Each is documented on the
endpoint.
Error envelope
{
"success": false,
"data": null,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Per-company per-category rate limit hit.",
"details": { "category": "autogenerator" }
}
}
Handlers may emit additional legacy keys alongside success, data, and
error. These are not part of the contract and may change without
notice.
Usage quotas and rate limits
For a single self-contained reference — all three tiers, the
429error codes, the response-header table, and a copy-pasteable backoff retry loop — see the dedicated Rate Limits page.
The Prezent API enforces three independent kinds of limits, applied in this order:
- Gateway throttle — a per-API-key request-rate + daily request cap enforced at the AWS API Gateway edge. Applies to every endpoint regardless of category.
- Per-minute rate limits — application-level, per-company ×
per-category throttling. Returns
HTTP 429withX-RateLimit-*headers when configured and exceeded. - Annual usage quotas — application-level, per-key caps on
specific billable operations (slide generation, presentation
downloads). Returns
HTTP 429witherror.code: "USAGE_LIMIT_EXCEEDED".
For any given request, the most restrictive of the three binds first. All three are configurable per company — contact your CSM to adjust.
Gateway throttle (default, applies to every key)
| Setting | Default |
|---|---|
| Steady request rate | 10 requests / second per API key |
| Burst capacity | 5 requests |
| Daily request quota | 1,000 requests / day per API key, across all endpoints |
Custom usage plans can raise these caps per customer. When you exceed
the throttle, API Gateway returns HTTP 429 with the canonical error
envelope and a Retry-After header.
Annual usage quotas
Default quotas for new customers (configurable per company):
| Operation | Default quota (per year) | Counted by |
|---|---|---|
Slide generation — POST /api/v2/generate, POST /api/v2/autogenerator/edit (and the 1.0 autogenerator / regenerate) | 50,000 requests / year | successful slides generated |
Presentation download — POST /api/v2/autogenerator/download, POST /api/v2/streams/sessions (and the 1.0 autogenerator/download) | 1,000,000 requests / year | successful downloads |
Template-Converter start — POST /api/v1/template-converter/start | Negotiated per customer | successful TC starts |
Template-Converter download — GET /api/v1/template-converter/download/{callbackId} | Negotiated per customer | successful TC downloads |
Quotas are tracked on the API key. When a key exceeds its quota the API
returns HTTP 429 with error.code: "USAGE_LIMIT_EXCEEDED". All other
endpoints (audiences, themes, upload, file-access, SCIM, status polls,
etc.) do not consume any annual quota.
The v2 AutoGenerator endpoints draw on the same two pools as their
1.0 counterparts — there is no separate v2 allowance, so migrating does
not change your budget. POST /api/v2/streams/sessions counts against
the download pool, since the stream it mints ends on an event
carrying the download_url.
Per-minute rate limits
Per-minute limits are enforced per company × API category, per 60-second sliding window. Three categories exist in production today:
| Category | Endpoints in this category | Default limit |
|---|---|---|
auto_generator | The AutoGenerator surface — /api/v2/generate, /api/v2/autogenerator/*, /api/v2/streams/sessions, /api/v1/autogenerator/* — plus /api/v1/audiences, /api/v1/audiences/search, /api/v1/themes, /api/v1/preprocess, /api/v1/validate, /api/v1/file-access | Configured per company — contact CS |
template_converter | All /api/v1/template-converter/* | Configured per company — contact CS |
scim | All /api/v1/scim/* | Configured per company — contact CS |
Endpoints not classified under one of the above (health checks) are not throttled by the per-minute limiter today — only the gateway throttle and annual quotas apply to them.
Per-minute limits are not enforced for any company until a row exists in
the api_rate_limits configuration for that company + category. In
practice the gateway throttle (1,000/day) is the most restrictive
default and will bind first for most workloads.
429 response shape
There are two distinct HTTP 429 surfaces in the stack — both use the
canonical error envelope, but they emit slightly different headers:
Gateway throttle 429 — emitted by AWS API Gateway when the
per-key 10 req/s, 5 burst, or 1,000 req/day cap is exceeded:
- Header:
Retry-After: 60(default; clients should back off ~60s) - Body: canonical error envelope;
error.codewill be"TOO_MANY_REQUESTS"
Application per-minute 429 — emitted by the Lambda's per-category rate limiter when configured per-company limits are exceeded:
| Header | Description |
|---|---|
X-RateLimit-Limit | Configured requests-per-window for the category. |
X-RateLimit-Remaining | Approximate requests remaining in the current window. |
X-RateLimit-Reset | Unix timestamp (seconds) when the window resets. |
Retry-After | Seconds the client should wait before retrying. |
Response body
{
"success": false,
"data": null,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded for this category. Try again later.",
"details": {
"category": "autogenerator",
"retry_after_seconds": 12
}
}
}
error.code will be one of TOO_MANY_REQUESTS (gateway),
RATE_LIMIT_EXCEEDED, USAGE_LIMIT_EXCEEDED, THROTTLED (image
search/replace), or MAX_RETRIES_EXCEEDED.
Error codes
error.code is a stable string from a fixed catalog — a code never changes
its meaning or HTTP status once published. Branch your error handling on
error.code (and the HTTP status), not on error.message.
The full catalog, grouped by HTTP status, lives on the dedicated Error Reference page. A few of the most common codes:
| HTTP | Code | Meaning |
|---|---|---|
400 | MISSING_REQUIRED_FIELD | A required field is absent. |
401 | INVALID_API_KEY | API key not found or not authorized. |
403 | FORBIDDEN | Access to the resource is forbidden. |
404 | RESOURCE_NOT_FOUND | The requested resource does not exist. |
409 | IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_BODY | Same Idempotency-Key, different body. |
422 | INVALID_INPUT | Input failed validation. |
429 | RATE_LIMIT_EXCEEDED | Per-company per-category rate limit hit. |
500 | INTERNAL_SERVER_ERROR | Unexpected server error. |
See the Error Reference for the complete list — including the webhook, streaming, and idempotency codes — and the uniform error envelope.
Async operations
Several Prezent endpoints kick off background work and return a
callback_id immediately. How you learn the work finished differs by
family:
| Family | Mechanism |
|---|---|
| AutoGenerator | Streaming — read Server-Sent Events |
| Template Converter | Polling — call a status endpoint |
Either family can also push completion to you via webhooks.
AutoGenerator — streaming
There is no status endpoint. The flow:
POST /api/v2/generate(or/api/v2/autogenerator/edit) returns the id atresData.callback_id.POST /api/v2/streams/sessionswith that id returns a short-livedstream_urlatdata.stream_url.- Open it with any SSE client and read events until
statusis no longerinprogress.
POST /api/v2/autogenerator/download returns a stream_url directly,
skipping step 2.
Every event carries {status, message, callback_id}, plus download_url
on a successful terminal event. Branch on status — inprogress, then
one of success, failed, cancelled.
Two things to get right:
- Set no read timeout. A generation is legitimately quiet for
stretches; a
:pingcomment every 15 seconds is what proves the connection is alive. download_urlmay benullon a success. On a generation stream that means the deck is built but not yet exported — call/api/v2/autogenerator/downloadand read that stream. It is not a failure.
On a dropped connection, reconnect with &last_event_id=<last id seen>;
if the token has expired, mint a fresh URL — the new stream replays the
whole turn. Full detail in Streaming (SSE).
Template Converter — polling
The Template Converter takes its callbackId in the path rather than as
a query parameter:
GET /api/v1/template-converter/status/{callbackId}
POST /api/v1/template-converter/start returns the id at top-level
callbackId.
The status endpoint returns 200 whenever the job is found — even when
the underlying workflow failed — so branch on the status field in the
body, never on the HTTP status.
Polling cadence: 2–5 seconds initially, with exponential backoff up to ~30 seconds. Most jobs terminate within 60–120 seconds; some run longer.
Idempotency
Every resource-creating write (POST/PUT/PATCH) accepts an
optional Idempotency-Key request header so you can safely retry a
request after a network error without creating a duplicate job.
- Send a unique key (a UUID is ideal) per logical operation:
Idempotency-Key: 1d8e…. - The first request is processed normally and the full response is cached for 24 hours.
- A retry with the same key and an identical body returns the
cached response verbatim, plus an
Idempotency-Replayed: trueresponse header — so the job is never created twice. - A retry with the same key but a different body returns
409 IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_BODY. Reuse a key only for true retries of the same request.
curl -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"}'
Idempotency is best-effort and fail-open: if the cache is briefly unavailable, the request is processed as a normal (non-replayed) call.
Pagination
List endpoints support opt-in cursor pagination. It is fully
backward-compatible: when you send neither limit nor cursor, the
endpoint returns the complete list exactly as before.
limit— items per page,1–200(default50). Sending it turns pagination on.cursor— opaque token from the previous response'snext_cursor.next_cursor— present in the response body;nullon the last page.
# First page
curl "https://api.prezent.ai/api/v1/audiences?limit=50" \
-H "Authorization: Bearer $PREZENT_API_KEY"
# -> { "items": [...], "next_cursor": "eyJpZHgiOjQ5fQ==" }
# Next page
curl "https://api.prezent.ai/api/v1/audiences?limit=50&cursor=eyJpZHgiOjQ5fQ==" \
-H "Authorization: Bearer $PREZENT_API_KEY"
Pagination is available on the list endpoints: /api/v1/audiences,
/api/v1/themes, /api/v1/autogenerator/templates,
/api/v1/template-converter/templates, and
/api/v1/webhook-subscriptions.
Best practices
- Keep your API keys secure. Do not commit them to source control or share them in screenshots.
- Use the right environment. Build and test against UAT
(
https://uatstage-api.myprezent.com) before promoting to production. - Respect rate limits. When you hit
429, honour theRetry-Afterheader. Use jittered exponential backoff for retries. - Poll with backoff. Do not poll status endpoints faster than every 2 seconds.
- Branch on
data.status, not the HTTP status. Status endpoints return200whenever the job is found, whatever its workflow state. - Pin to documented fields. Handlers may emit additional legacy keys alongside the contract; do not depend on them.
Where to go next
| If you want to | Go to |
|---|---|
| Browse every endpoint interactively | API Reference |
| Set up authentication | Getting Started → Authentication |
| Generate your API key | API Keys |
| See API usage and quotas | API Usage |
| Get integration help | Help |
| Stay current on changes | Change Log |