codai docs
Gateway

Share, review and remix

Public read-only links to a creative, review links with anchored comments and approval, and remix of a shared creative into your own account.

A creative can be shared through a link. A view link opens a public, read-only page with the preview; when you allow it, anyone with a codai API key can remix it into their own account. A review link opens a page where people without an account leave comments pinned to a node and a moment of the video, and — when you allow it — approve the creative or request changes.

Everything on this page is free: no model calls, no renders.

MethodPathResult
POST/v1/studio/creatives/{id}/sharesCreate a view or review link (201, token shown once)
GET/v1/studio/creatives/{id}/sharesActive links of a creative, newest first
DELETE/v1/studio/creatives/{id}/shares/{shareId}Revoke a link (204)
GET/v1/studio/creatives/{id}/reviewReview status, approved version and thread counts
POST/v1/studio/creatives/{id}/review{ action: "request" } or { action: "reset" }
GET/v1/studio/creatives/{id}/review/threads?status=Comment threads (open, resolved or all)
POST/v1/studio/creatives/{id}/review/threadsNew owner thread (201)
POST/v1/studio/creatives/{id}/review/threads/{threadId}/repliesOwner reply (201)
POST/v1/studio/creatives/{id}/review/threads/{threadId}/resolveMark a thread resolved
POST/v1/studio/creatives/{id}/review/threads/{threadId}/reopenReopen a thread
DELETE/v1/studio/creatives/{id}/review/comments/{commentId}Delete a comment (204)
POST/v1/studio/shares/{token}/remixCopy a shared creative into your account (201)
GET/v1/public/studio/shares/{token}?format=&locale=Public page data (no authentication)
POST/v1/public/studio/reviews/{token}/threadsReviewer comment (no authentication, 201)
POST/v1/public/studio/reviews/{token}/threads/{threadId}/repliesReviewer reply (201)
POST/v1/public/studio/reviews/{token}/threads/{threadId}/resolveReviewer resolves a thread
POST/v1/public/studio/reviews/{token}/threads/{threadId}/reopenReviewer reopens a thread
POST/v1/public/studio/reviews/{token}/decisionApprove or request changes (approver links only)
curl https://ai.codai.ro/v1/studio/creatives/<id>/shares \
  -H "Authorization: Bearer $CODAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "kind": "review", "label": "Client — Ana", "can_approve": true, "expires_in_days": 14 }'
FieldMeaning
kindview (public read-only page, /s/<token>) or review (comments and decisions, /r/<token>)
labelYour own note, up to 100 characters (for example who received the link)
expires_in_days1 to 365, or "never"; without it the link expires after 30 days
seqView links only: pin the page to this version (400 unknown_seq when it does not exist); default follows the head
allow_remixView links only: whether visitors may remix (default false; remix is opt-in)
can_approveReview links only: whether this link may approve or request changes (default false)

The answer is 201 { "id", "object": "studio.share", "kind", "token", "url", "label", "pinned_seq", "allow_remix", "can_approve", "expires_at", "created_at" }. The token and the full url are returned only once: codai keeps just a SHA-256 hash of the 256-bit token, so a lost link cannot be shown again — revoke it and create another one. The listing returns the same fields with url: null, without token and with last_used_at.

DELETE …/shares/{shareId} revokes a link at once (404 when it is unknown or already revoked). An expired, revoked link, or one whose creative was deleted, answers 404 Share link not found or expired everywhere — the same answer as a token that never existed.

The public page

https://hub.codai.ro/s/<token> shows the title, the preview (video and documents play in a sandboxed frame), a format and language switcher and, when allowed, Remix in codai. A view link shows its pinned version or the head; a review link always shows the head. The same data comes from GET /v1/public/studio/shares/{token}: kind, title, creative_kind, seq, doc_hash, allow_remix, can_approve, formats, default_format, locales, compiled ({ format, width, height, duration_ms, html }, or null for images) and, for review links, review and threads. Asset URLs inside the preview are signed for 1 hour. Public answers are never cached or indexed (cache-control: private, no-store, x-robots-tag: noindex, nofollow, referrer-policy: no-referrer).

Remix

POST /v1/studio/shares/{token}/remix (any codai API key, optional { "title" }) copies the shared version into your account and answers 201 with the new creative plus remixed_from: { share_id, seq }:

  • the owner's ready assets used by the document are copied into your Studio library (at most 200 assets and 1 GiB, otherwise 413 remix_too_large); missing or unfinished assets stay as references and are listed in warnings;
  • the brand kit link is dropped (the kit belongs to someone else) — the colours and fonts already in the document stay;
  • when you own the shared creative, remix is a normal fork.

Only view links with allow_remix can be remixed; any other link answers 404. Remixing is free and limited to 20 per minute per key.

Review

A review has a status: draft → in_review → approved or changes_requested.

  • POST …/review with { "action": "request" } opens the review for the current head (requested_seq) and clears an earlier decision; { "action": "reset" } goes back to draft.
  • Only a reviewer on a link created with can_approve: true can decide, with POST /v1/public/studio/reviews/{token}/decision { "name", "decision": "approve" | "request_changes", "seq", "note"? }. Errors: 403 not_an_approver, 409 review_not_open (the status is not in_review) and 409 stale with head_seq when seq is not the current head — the reviewer reloads and decides on what you see now.
  • An approval pins the version: approved_seq and approved_doc_hash. GET …/review returns approved_is_head, so you can tell when the creative changed after it was approved. Each decision also appears in the threads as a resolved comment of kind decision, with the note.

GET …/review answers { "object": "studio.review", "creative_id", "status", "head_seq", "requested_seq", "requested_at", "approved_seq", "approved_doc_hash", "approved_is_head", "decided_by", "decided_at", "decision_note", "threads": { "open", "total" } }.

Comments and anchors

A thread is a root comment plus its replies. Each thread may be anchored with node_id, scene_id and t_ms (0 to 3 600 000 ms), checked against the head: 400 unknown_node or 400 unknown_scene. When only node_id is given the scene is derived from it; when only t_ms is given on a video, the scene playing at that moment is used. A comment body has 1 to 2000 characters.

A thread is { "id", "node_id", "scene_id", "t_ms", "seq", "status": "open" | "resolved", "resolved_by", "resolved_at", "created_at", "comments" }; each comment is { "id", "kind", "decision", "author": { "kind": "owner" | "reviewer", "name" }, "body", "created_at" }, the first one being the root. The owner's name is always null (apps show "Owner"). Reviewers send a name (1 to 80 characters, otherwise 400 invalid_name) with every comment, reply, resolve or reopen. The owner can resolve, reopen and delete any comment; deleting a root hides the whole thread.

Limits

LimitValue
Active links per creative20 (409 too_many_shares)
Threads per creative500 (409 too_many_comments)
Replies per thread100 (409 too_many_comments)
Comment / note2000 characters
Reviewer name80 characters
Public reads60 per minute per IP, 300 per minute per link
Public writes10 per minute per IP and link
Remix20 per minute per key; 200 assets, 1 GiB

Privacy

Reviewer names and comments are visible to the owner and to everyone else holding a review link of the same creative. They are stored with the creative and are deleted with it (and with the owner's account). The owner's name is never shown. Tokens are stored only as hashes; codai never logs tokens, signed URLs, comment bodies or reviewer names.

SDKs and agent tools

const link = await codai.creatives.createShare(creative.id, { kind: 'review', can_approve: true, expires_in_days: 14 });
console.log(link.url); // shown once
await codai.creatives.requestReview(creative.id);
const threads = await codai.creatives.reviewThreads(creative.id, { status: 'open' });
const copy = await codai.shares.remix('https://hub.codai.ro/s/<token>', { title: 'My version' });
link = client.creatives.create_share(creative["id"], kind="review", can_approve=True, expires_in_days=14)
print(link["url"])  # shown once
client.creatives.request_review(creative["id"])
threads = client.creatives.review_threads(creative["id"], status="open")
copy = client.shares.remix("https://hub.codai.ro/s/<token>", title="My version")

The SDKs also have listShares / list_shares, revokeShare / revoke_share, review, resetReview / reset_review, the thread methods and, on shares, get, comment, reply, resolve, reopen and decide for the public review flow. They accept a raw token or a full /s/… or /r/… URL.

Agents on desktop, phone and VS Code use creative_share (creative_id, kind, can_approve, allow_remix, expires_in_days, label), creative_review (action: status, request or reset; threads), creative_review_comment (action: comment, reply, resolve or reopen; body, thread_id, node_id, t_ms) and creative_remix (share, title).

Hub (internal)

The hub calls the owner routes under /internal/studio/creatives/:id/shares… and /internal/studio/creatives/:id/review…, and remix under /internal/studio/shares/:token/remix, with a service token and a user_id; bodies and errors are identical. The public pages call the public routes directly.

On this page