Use the Clevera REST API
Call Clevera from your own scripts: base URL, bearer-token authentication, endpoints and the permission each needs, the quote-then-start flow for paid work, idempotency, error format and rate limits.
Clevera's REST API lets your own scripts and services do what an agent can do over MCP: read your library, request videos and articles, export videos, work on doc sites and follow the jobs. This article covers the base URL, authentication, the request flow for paid work, errors and rate limits.
Basics
| Base URL | https://app.clevera.ai/api/v1 |
| Authentication | Authorization: Bearer <token> with an API token (it starts with clv_agent_) |
| Format | JSON in and out. Send Accept: application/json and, with a body, Content-Type: application/json. |
| Ids | Public ids, such as job_… for jobs. Use the ids the API returns. |
Check a token with GET /docs/me:
curl -H "Authorization: Bearer $CLEVERA_TOKEN" \
-H "Accept: application/json" \
https://app.clevera.ai/api/v1/docs/me
The answer says who the token acts as: the token's name and expiry, the person and their current role, the workspace, the sites in scope and the permissions that work right now (the token's permissions trimmed to the person's current role). Call it first when a call is refused.
Endpoints
Each endpoint needs the permission shown. Calling one without it returns 403 forbidden_ability. See Agent permissions.
Library and materials
| Method and path | Permission | What it does |
|---|---|---|
GET /create/types |
any | The video and social clip types you can request. |
GET /library |
library:read |
Videos, recordings and articles the token's owner can see. |
GET /recordings |
library:read |
Recordings only. |
GET /library/{item} |
library:read |
One item. |
GET /library/{item}/transcript |
library:read |
Its transcript. |
GET /library/{item}/article |
library:read |
Its article. |
GET /library/{item}/embed |
library:read |
Its embed code. |
GET /materials |
library:read |
Uploaded images, videos and PDFs. |
POST /materials, POST /materials/import, POST /materials/uploads, POST /materials/uploads/{upload_id}/complete |
materials:write |
Add an image, video or PDF (directly, from a URL, or as a large upload). |
Videos and articles
| Method and path | Permission | What it does |
|---|---|---|
POST /videos/quotes |
videos:create |
Quote a video from a recording (type: how_to, product_demo, cleanup, styled_video), an article from a recording (article) or a translation (translation). |
POST /videos |
videos:create + credits:spend |
Make the quoted video (quote_id). |
POST /articles/from-recording |
videos:create + credits:spend |
Make the quoted article. |
POST /videos/translations |
videos:create + credits:spend |
Make the quoted translation. |
POST /clips/quotes |
videos:create |
Quote a social clip (types from GET /create/types). |
POST /clips |
videos:create + credits:spend |
Make the quoted social clip. |
POST /videos/{video_id}/exports |
videos:export |
Render an MP4: resolution 1080p (default), 2k or 4k; always 60 fps. Free. |
Jobs and credits
| Method and path | Permission | What it does |
|---|---|---|
POST /quotes |
the work's permission | A quote for any job kind. |
POST /jobs |
the work's permission (+ credits:spend when paid) |
Start a quoted job. |
GET /jobs |
jobs:read |
List jobs. |
GET /jobs/{job} |
jobs:read |
One job's status and result. |
GET /jobs/{job}/wait |
jobs:read |
Wait for a change instead of polling. |
GET /jobs/{job}/events |
jobs:read |
The job's progress events. |
POST /jobs/{job}/cancel |
jobs:read |
Cancel a job. Too late: "This job can no longer be canceled." |
GET /credits |
credits:spend or jobs:read |
The workspace's credit balance. |
Doc sites
| Method and path | Permission | What it does |
|---|---|---|
GET /docs/sites, GET /docs/sites/{site}, GET /docs/sites/{site}/tree, GET /docs/sites/{site}/pages |
content:read |
Sites in the token's scope and their pages. |
GET /docs/sites/{site}/search, GET /docs/pages/{page}, GET /docs/pages/{page}/revisions |
content:read |
Search and read pages, drafts included. |
POST /docs/sites/{site}/articles, PATCH /docs/pages/{page}/article, POST /docs/pages/{page}/review |
articles:write |
Create and edit draft articles, submit for review. Live articles also need site:publish. |
PATCH /docs/pages/{page}, DELETE /docs/pages/{page}, POST /docs/sites/{site}/sections, PATCH /docs/sections/{section} |
structure:write |
Move, rename, hide and remove pages; sections. |
GET/POST /docs/sites/{site}/site-pages, PUT /docs/site-pages/{page}/body |
content:read / site-pages:write |
Home, contact and legal pages. |
GET/POST /docs/sites/{site}/changelog, PATCH /docs/changelog/{entry} |
content:read / changelog:write |
Changelog entries as drafts. |
POST /docs/media, POST /docs/media/uploads |
media:write |
Upload images. |
POST /docs/sites/{site}/publish, POST /docs/pages/{page}/ready, POST /docs/changelog/{entry}/publish |
site:publish |
Publish what readers see. |
GET /insights/sites/{site}, …/gaps, …/feedback |
insights:read |
Search gaps, unanswered questions, page feedback. |
PATCH /docs/sites/{site}/settings, …/appearance, PUT …/navigation, POST …/redirects |
site:configure |
Site settings. |
POST /docs/sites |
sites:create |
Create a doc site. |
More on agents and doc sites: Connect AI agents to your doc sites.
Request paid work
Work that costs credits always goes quote first, then start:
- Quote it.
POST /videos/quotes(or/clips/quotes) with what you want. The answer has aquote_idand the credit range. A quote is valid for 15 minutes and can be used once. - Optionally dry-run it. Send the start with
"dry_run": trueto learn whether it would start, need approval or be blocked. Nothing is written. - Start it.
POST /videoswithquote_idand anIdempotency-Keyheader. The answer is202with a job. - Follow it.
GET /jobs/{job}/waituntil the job'sstatuschanges, or listen for webhooks.
curl -X POST https://app.clevera.ai/api/v1/videos/quotes \
-H "Authorization: Bearer $CLEVERA_TOKEN" -H "Content-Type: application/json" \
-d '{"type": "how_to", "recording_id": "<recording id>", "language": "en-US"}'
curl -X POST https://app.clevera.ai/api/v1/videos \
-H "Authorization: Bearer $CLEVERA_TOKEN" -H "Content-Type: application/json" \
-H "Idempotency-Key: 3f6c1a2e-8d4b-4f7a-9c1e-2b5d7e9f0a13" \
-d '{"quote_id": "<quote id>"}'
Job statuses:
| Status | Meaning |
|---|---|
queued |
Accepted, about to run. |
running |
In progress. |
needs_input |
Waiting for a person, usually an approval on Agent requests. The job carries a link and an expiry. |
succeeded |
Done. The job links the new video or article. |
failed |
It failed; the job has an error_code. |
canceled |
Canceled, or its approval was denied. |
expired |
Nobody approved it within 24 hours. |
Whether a start runs at once or waits for a person depends on the token's spend caps and its Approve automatically below setting. See Control agent spending and approvals.
Retries and idempotency
Send an Idempotency-Key header (a fresh UUID per action) on every create and start. If the network drops and you retry with the same key and body, you get the first answer back instead of a second video. Keys are remembered for 24 hours.
| Code | Meaning |
|---|---|
idempotency_key_reused |
The same key with a different body. Use a new key for a new request. |
idempotency_in_progress |
The first request with this key is still running. Wait and retry. |
idempotency_conflict |
"This idempotency key was used for a different request." |
Errors
Every error has the same shape, with a message that says what to do next:
{
"error": {
"code": "forbidden_ability",
"message": "This token lacks the videos:create ability. Ask the workspace member who owns it for a token that has it.",
"details": { "ability": "videos:create" }
},
"request_id": "req_example"
}
Include the request_id when you contact support.
| HTTP | Codes | Typical cause |
|---|---|---|
| 401 | unauthenticated, token_expired, token_revoked |
No token, a wrong one, or one that expired or was revoked. |
| 402 | insufficient_credits |
The workspace doesn't have enough credits for the quote. |
| 403 | forbidden_ability, forbidden_role, forbidden_item, ip_not_allowed, live_content_needs_publish, site_paused, forbidden |
A missing permission, the owner's role, collection access or the IP allowlist. |
| 403 | plan_locked |
"The agent API is not on this workspace's plan. It is on Pro and up." |
| 404 | not_found, unknown_kind |
"No … with that id in this token's scope. List or search first and use a returned id." |
| 409 | revision_conflict, quote_used, not_cancelable, idempotency_* |
The content changed, the quote was used, or a retry clash. |
| 410 | quote_expired |
"This quote has expired. Ask for a new quote." |
| 413 | unsupported_media |
The file is too large or not a supported type. |
| 422 | validation_failed, invalid_input, quote_mismatch, limit_reached |
A field is wrong; details names it. |
| 429 | rate_limited, cap_exceeded, busy |
Too many requests, a spend cap, or two starts at once. |
Every message, with the fix: Fix agent and API errors.
Rate limits
| Limit | Value | Message |
|---|---|---|
| Requests per token | 300 a minute | "This token is over its request rate. Wait and retry." |
| Requests per workspace | 1,200 a minute, all tokens together | "This workspace is over its agent request rate. Wait and retry." |
| Writes per token | 60 a minute | "Too many writes from this token. Wait and retry." |
| Writes per token per day | 2,000 | "This token reached its daily write limit. Try again tomorrow." |
| Publishes per token | 10 an hour | "This token reached its hourly publish limit. Try again later." |
| Paid starts | 20 an hour per token, 100 a day per workspace | rate_limited with retry_after |
| Uploads | 30 a minute; 500 MB a day per token; 25 MB per file | "Too many uploads from this token. Wait and retry." / "This token reached its daily upload volume. Try again tomorrow." |
| Calls without a valid token | 60 a minute per IP address | "Too many requests. Wait and retry." |
A 429 answer has a Retry-After header and retry_after (seconds) in the body. Wait that long before retrying. Reads, quotes and status checks cost no credits.