This is the full list of what the RecReview public API accepts and returns. To create a key and choose its permissions, start with API keys and the public API.
Before you start: the API needs a paid Studio subscription. Creator, Pro and the free trial don’t include it.
Basics
- Base URL:
https://rec.review/api/v1 - Authentication: send
Authorization: Bearer rr_live_...on every request. Each key belongs to one workspace, so you never pass a workspace id. - Format: request and response bodies are JSON. Fields the API doesn’t know are refused with a
400error. - Dates: ISO 8601 with time, such as
2026-10-30T15:00:00.000Z. - Responses: success is
{ "success": true, "data": ... }. Errors are{ "success": false, "error": "...", "code": "..." }.
Endpoints
| Call | Permission | What it does |
|---|---|---|
GET /me |
Any | Shows the key’s name, permissions and workspace |
POST /tasks |
Create tasks | Creates a video or photo gallery task |
GET /tasks |
Read tasks | Lists tasks, most recently updated first |
GET /tasks/:id |
Read tasks | Reads one task with its links, tags and versions |
PATCH /tasks/:id |
Update tasks | Updates a task |
POST /tasks/:id/attachments |
Update tasks | Adds links to a task |
GET /tasks/:id/comments |
Read review comments | Reads the comments on a version |
POST /tasks/:id/verdict |
Record the client verdict | Records what the client decided outside the app |
GET /time-entries |
Read time entries | Reads logged hours |
GET /clients |
Read clients | Lists clients |
POST /clients |
Create clients | Adds a client |
GET /projects |
Read projects | Lists projects, optionally by clientId |
POST /projects |
Create projects | Adds a project |
GET /members |
Read members | Lists the people a task can be assigned to |
GET /workflow |
Read statuses, phases and blockers | Lists your status keys, phase keys and blocker ids |
Create a task
POST /tasks returns 201 with the task. Only title is required.
| Field | Type | Notes |
|---|---|---|
title |
text, up to 256 characters | Required |
kind |
video or gallery |
Defaults to video |
description |
text, up to 5,000 characters | |
clientId |
id | A client in the workspace |
projectId |
id | The client comes from the project. If you also send clientId, it must match |
assignedToUserId |
id | An active member, from GET /members |
status |
key | From GET /workflow. An unknown status falls into the first column |
phase |
key | From GET /workflow |
waitingForBlockerId |
id | From GET /workflow |
dueDate |
date | The client deadline |
internalDueDate |
date | The team deadline. It must be on or before dueDate |
isUrgent |
true or false | |
priority |
low, medium, high or urgent |
|
tags |
list of text, up to 20 | |
estimatedHours |
number | |
talent |
text | Video tasks only |
estimatedVideoDuration |
whole number | Video tasks only |
attachments |
list of up to 20 { "type": "link", "name": "...", "url": "..." } |
Absolute http or https links. type can be left out |
Send an Idempotency-Key header, up to 255 characters, based on the event that triggered the request. If the same key and body arrive again, you get the task already created, with a 200 and an Idempotent-Replayed: true header. The same key with a different body returns 422.
List tasks
GET /tasks accepts these filters:
| Parameter | Notes |
|---|---|
clientId, projectId, assignedToUserId |
Only tasks that match |
status, phase |
Keys from GET /workflow |
q |
Text search |
kind |
video (default), gallery or all |
limit |
Up to 200. Defaults to 50 |
cursor |
The nextCursor value from the previous page |
The response is { "success": true, "data": [...], "nextCursor": "..." }. When nextCursor is null, there are no more pages.
Each item has id, kind, title, videoCode, status, phase, clientId, projectId, assignedToUserId, waitingForBlockerId, isUrgent, dueDate, internalDueDate, createdAt, updatedAt and url.
GET /tasks/:id adds description, tags, attachments, gallery and versions. Each version has id, versionNumber, title, createdAt, isLatestVersion, reviewStatus and reviewVerdict.
Update a task
PATCH /tasks/:id accepts title, description, status, phase, isUrgent, assignedToUserId, waitingForBlockerId, dueDate, internalDueDate, tags, estimatedHours and talent. Send only what changes. Send null to clear a field, except title, status, isUrgent and tags.
Changing the status, phase or blocker runs your automations. The client and project of a task can’t be changed through the API.
Add links
POST /tasks/:id/attachments takes { "attachments": [{ "type": "link", "name": "Script", "url": "https://..." }] }. It adds up to 20 links per call and keeps the existing ones. A task holds at most 50.
Read comments
GET /tasks/:id/comments returns the latest version. Send versionId to read another one. The response is { "success": true, "data": { "version": { "id", "versionNumber" }, "comments": [...] } }.
Each comment has id, timestamp (seconds into the video), timelineEndTimestamp, content, type, status, isPrivate, authorName, authorIsTeam, createdAt, resolvedAt, attachmentsCount and replies. Team-only comments are included.
Record a client verdict
POST /tasks/:id/verdict takes:
| Field | Values |
|---|---|
verdict |
approved or changes_requested. Required |
channel |
whatsapp, email, meeting or other. Required |
sendFinalEmail |
true or false. Applies to approvals, and defaults to sending |
Warning: an approval delivers the final video. RecReview emails the client and sends the
video.delivery_approvedwebhook, unless you send"sendFinalEmail": false, which only turns off the email.
It only works on the latest version. A version that is already approved, or that already has this verdict, returns 409.
Read hours
GET /time-entries accepts from, to, clientId, projectId, taskId, userId and limit. The limit goes up to 5,000 and defaults to 500. This list has no pages, so narrow the dates if you need more.
Each entry has id, userId, userName, taskId, projectId, versionId, title, notes, startedAt, stoppedAt, durationSeconds and isRunning.
Clients and projects
POST /clients needs name and code. The code has 2 to 12 letters or numbers and becomes the prefix of the client’s video codes. contactName, contactEmail and contactPhone are optional. A code already in use returns 409.
POST /projects needs name and clientId. code, description and dueDate are optional.
GET /clients and GET /projects return every record at once, with no pages.
Errors
| Status | Codes | Meaning |
|---|---|---|
400 |
invalid_request, invalid_idempotency_key |
Something in the request is invalid, or an id sent in the body isn’t in this workspace. invalid_idempotency_key means the Idempotency-Key header is invalid |
401 |
missing_api_key, invalid_api_key, api_key_revoked, api_key_expired, api_key_creator_inactive |
The key can’t be used |
403 |
insufficient_scope |
The key doesn’t have this permission |
403 |
plan_required, trial_expired, subscription_inactive |
The workspace isn’t on a paid Studio subscription |
404 |
not_found |
The task or version in the URL doesn’t exist, or it belongs to another workspace |
409 |
conflict, attachment_limit, no_version, already_approved, already_recorded, verdict_changed, not_latest_version, idempotency_in_progress, idempotency_resource_gone |
The request conflicts with the current state |
422 |
idempotency_key_reused |
The same Idempotency-Key came with a different body |
429 |
rate_limited, daily_task_limit |
Over a limit. Wait and try again |
Limits
- 120 requests per minute per key.
- 2,000 tasks created through the API per workspace every 24 hours.
- Too many failed sign-in attempts from the same address are blocked for a few minutes.
To react to events instead of asking for them, use webhooks.