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.
| Method | Path | Result |
|---|---|---|
POST | /v1/studio/creatives/{id}/shares | Create a view or review link (201, token shown once) |
GET | /v1/studio/creatives/{id}/shares | Active links of a creative, newest first |
DELETE | /v1/studio/creatives/{id}/shares/{shareId} | Revoke a link (204) |
GET | /v1/studio/creatives/{id}/review | Review 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/threads | New owner thread (201) |
POST | /v1/studio/creatives/{id}/review/threads/{threadId}/replies | Owner reply (201) |
POST | /v1/studio/creatives/{id}/review/threads/{threadId}/resolve | Mark a thread resolved |
POST | /v1/studio/creatives/{id}/review/threads/{threadId}/reopen | Reopen a thread |
DELETE | /v1/studio/creatives/{id}/review/comments/{commentId} | Delete a comment (204) |
POST | /v1/studio/shares/{token}/remix | Copy 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}/threads | Reviewer comment (no authentication, 201) |
POST | /v1/public/studio/reviews/{token}/threads/{threadId}/replies | Reviewer reply (201) |
POST | /v1/public/studio/reviews/{token}/threads/{threadId}/resolve | Reviewer resolves a thread |
POST | /v1/public/studio/reviews/{token}/threads/{threadId}/reopen | Reviewer reopens a thread |
POST | /v1/public/studio/reviews/{token}/decision | Approve or request changes (approver links only) |
View and review links
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 }'| Field | Meaning |
|---|---|
kind | view (public read-only page, /s/<token>) or review (comments and decisions, /r/<token>) |
label | Your own note, up to 100 characters (for example who received the link) |
expires_in_days | 1 to 365, or "never"; without it the link expires after 30 days |
seq | View links only: pin the page to this version (400 unknown_seq when it does not exist); default follows the head |
allow_remix | View links only: whether visitors may remix (default false; remix is opt-in) |
can_approve | Review 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 inwarnings; - 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 …/reviewwith{ "action": "request" }opens the review for the current head (requested_seq) and clears an earlier decision;{ "action": "reset" }goes back todraft.- Only a reviewer on a link created with
can_approve: truecan decide, withPOST /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 notin_review) and409 stalewithhead_seqwhenseqis not the current head — the reviewer reloads and decides on what you see now. - An approval pins the version:
approved_seqandapproved_doc_hash.GET …/reviewreturnsapproved_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 kinddecision, 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
| Limit | Value |
|---|---|
| Active links per creative | 20 (409 too_many_shares) |
| Threads per creative | 500 (409 too_many_comments) |
| Replies per thread | 100 (409 too_many_comments) |
| Comment / note | 2000 characters |
| Reviewer name | 80 characters |
| Public reads | 60 per minute per IP, 300 per minute per link |
| Public writes | 10 per minute per IP and link |
| Remix | 20 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.
Batches
Fill a template or a creative from a CSV file or a sheet — one creative per row, with optional per-row language and render, status export and a ZIP of the videos.
Sound effects
codai Studio sound-effects library — search curated CC0 sounds, import them as assets for free and use them in renders.