Skip to content
Sign in Waitlist
Docs/Authentication and errors

Authentication, errors and limits

Everything that applies to every route: how to authenticate, what each scope allows, the error format and how many requests fit in a minute.

Authentication

Send your API key in the Authorization header with the Bearer prefix. The base URL is https://praeko.app; everything is JSON in UTF-8.

Headers
Authorization: Bearer praeko_…
X-Praeko-Contract: en
Item Detail
Key format Starts with praeko_. Older keys start with arauto_ and still work.
X-Praeko-Contract: en Selects the English contract on the paths that exist in both contracts (/v1/posts, /v1/insights, /v1/youtube/videos). Always send it.
Secret Shown once, when you create the key. Praeko stores only the hash.
Panel cookie For the panel only. Programs should use an API key.
AI agents (MCP) The MCP server at https://praeko.app/mcp accepts the API key or an OAuth sign-in (the agent opens a consent screen and you choose the access). See MCP server.
Keep the key out of your codeUse an environment variable or a secrets vault. If it leaks, revoke it under API keys and create another one.

Scopes

Each key has one scope and each level includes the one before. The minimum scope of each route shows as a badge in the reference.

Scope Allows Routes
read Read channels, posts, calendar, metrics, comments, usage. GET on most resources
write Create, edit and cancel posts; upload media; reply to comments; slots; ideas. POST, PUT, PATCH, DELETE on content
admin Keys, webhooks, Instagram token, metrics import. api-keys, webhooks, insights/import

Errors

The HTTP status is the status of the failure. The body always has the same envelope; code is stable, and message is human-readable text, currently in Portuguese.

422
{
  "error": {
    "code": "time_in_past",
    "message": "tiktok: 2026-11-01T10:00:00Z já passou ou é daqui a menos de 30 s",
    "details": {}
  }
}
Status code Means
400 empty_body, invalid_json Empty body, or a body that is not a JSON object.
401 unauthorized, invalid_api_key, revoked_api_key, expired_api_key No key, or a key that does not exist, was revoked or has expired. Includes WWW-Authenticate: Bearer.
403 forbidden The key's scope is not enough.
404 post_not_found, media_not_found, webhook_not_found… The resource does not exist in this workspace.
409 channel_not_connected, no_slots, media_not_ready… The current state blocks the action.
413 body_too_large The body is over 1 MB.
422 invalid_field, invalid_request, time_in_past… Invalid field; details.errors lists all of them. Portuguese field names are rejected.
429 rate_limited Per-minute limit. Includes Retry-After.
502 youtube_error, instagram_error, tiktok_unavailable, buffer_error The network refused the request; its message comes in the body.

The full list of contract codes, with status and meaning, is in Errors and limits.

Limits

Limit Value
Requests 300 per minute per key (approximate, per instance). Over the limit: 429 with Retry-After.
JSON body 1 MB
Media file Up to 50 MiB in one request (simple: true); above that, in parts of at least 5 MiB
Webhooks 10 per workspace; each delivery has a 10 s timeout
Usage log 30 days, metadata only

Idempotency

Send the Idempotency-Key header (a UUID) on POST, PATCH and DELETE, and a retry after a network failure returns the first response, with Idempotent-Replayed: true, without creating anything new. The key lasts 24 hours, per workspace and per route. A key reused with a different request returns 422 idempotency_key_reuse; a first request that is still running returns 409 idempotency_in_progress. Without the header nothing changes. Details, curl, SDK and CLI in Retry a request safely.

Retry without duplicating
curl -X POST https://praeko.app/v1/posts \
  -H "Authorization: Bearer $PRAEKO_KEY" -H "X-Praeko-Contract: en" \
  -H "Idempotency-Key: $(uuidgen)" -H "Content-Type: application/json" -d @post.json

Versions and changelog

The version is in the path: /v1. The Portuguese paths still answer, marked with Deprecation: true and Link: …; rel="successor-version". The date to switch them off has not been set. The public changelog lists the changes, with the date of each one.

Deprecated paths

These Portuguese paths still work and answer with Deprecation: true and Link: <new>; rel="successor-version": the Portuguese /v1/... aliases (for example /v1/canais, instead of /v1/channels), /saude (use /health) and /conexoes/:network/retorno (use /connections/:network/callback). In the panel, the old addresses (#/publicar, #/canais, #/conectar-agente…) are rewritten to the new ones (#/publish, #/channels, #/connect-agent…) and /entrar redirects (301) to /sign-in. Move your integrations to the new paths. Before any of them is switched off, the notice appears here in the changelog, at least 90 days ahead; the date has not been set.

Question or mistake on this page? contato@praeko.appView .md

Type to search pages, routes and error codes.