Teams, reviews and the API
Invite a team, review and approve ads, share review links with clients, reuse layouts as templates, and read finished ads through the API and webhooks.
4 min readUpdated Oct 17, 2026Applies to Adcraft 1.0.0
On this page
Team and roles
Each workspace has owners, editors and viewers. Owners invite people under Settings → Team; invitations are emailed when Resend is configured, and can always be copied as a link. They expire after 7 days and must be accepted with the invited address. The full permission table is on First admin and the admin panel.
A person can be a member of more than one workspace. Accepting an invitation opens that workspace, but 1.0.0 has no workspace switcher in the interface (the invitation page suggests the sidebar, which has a brand switcher only), so for now each person is best kept to one workspace.
Comments and approvals
Open an ad's Review page to discuss and approve it.
- Comments can be left by anyone in the workspace, pinned to a particular size, and marked resolved.
- Approval status moves through Draft, In review, Approved and Changes requested. Owners and editors can Request approval, Approve, Request changes and reopen a decision; viewers can only comment.
- The Next panel on a finished ad suggests what to do: approve, send for review, add to a campaign or make a variant.
Workspace owners can require approval before publishing under Settings → Guardrails, so only approved ads can be added to campaigns.
Client review links
From the review page, owners and editors can Create link for a client who has no account:
| Option | Default |
|---|---|
| Allow comments | On |
| Allow approve or request changes | Off |
| Expires in | 14 days (7, 14, 30 days or never) |
The client sees every size of the ad, gives their name, and can comment or decide if allowed. Their entries appear in the review thread marked "(client)". Links can be copied and revoked at any time; expired and revoked links say so.
Note
The code can also serve a link to a gallery of a brand's approved ads, but no screen creates one in 1.0.0. Review links are per ad.
Templates
On an ad's review page, Save as template keeps its layout, scene and product placement for reuse, for the current brand or shared with every brand in the workspace. Templates appear as Saved brand layouts when you make an editable static ad, and are listed under Settings → Templates, where owners and editors can delete them. Templates saved from videos are listed but not used by the video builders.
Activity and notifications
- The activity tray in the top bar shows running jobs and the last 24 hours of work.
- When a video, character, look or digital twin finishes or fails, owners and editors get an email (with Resend configured). Owners can turn this off under Settings → Guardrails.
Audit log
Owners see the workspace's audit log under Settings → Audit log: team changes, settings, API keys, approvals, publishing and similar actions. Platform admins see every workspace's entries, plus their own actions, under Admin → Audit log.
Public API
A small read-only REST API lets other systems fetch finished ads. Owners create and revoke keys under Settings → API access; a key is shown once, starts with ak_live_, and only its hash is stored.
curl https://ads.example.com/api/v1/creatives?limit=50 \
-H "Authorization: Bearer ak_live_..."| Endpoint | Returns |
|---|---|
GET /api/v1/creatives |
{ data, next_cursor }. Query: brandId, limit (up to 100), cursor (the next_cursor from the previous page). |
GET /api/v1/creatives/:id |
{ data } for one ad |
GET /api/v1/files/<key> |
A rendered file, for keys in the API key's workspace |
Each creative has id, name, kind (static, video or ugc), brand, approval and renders. Each render has variantId, placement, label, ratio, width, height, status and a url to download it with the same key.
The API cannot create or generate anything. A missing, revoked or unknown key gets 401, and so does any key of a suspended workspace until it is reinstated.
Webhooks
Owners add webhook endpoints under Settings → API access and choose events (none chosen means all):
| Event | When |
|---|---|
creative.rendered |
A static ad's sizes have all rendered |
approval.approved |
An ad was approved, in the app or through a review link |
approval.changes_requested |
Changes were requested |
comment.added |
A comment was added, in the app or through a review link |
Each delivery is a POST with a JSON body { id, event, orgId, createdAt, data } and these headers:
x-adcraft-event: creative.rendered
x-adcraft-timestamp: 1792224000
x-adcraft-signature: sha256=<hex>The signature is an HMAC-SHA256 of <timestamp>.<raw body> with the endpoint's secret (shown once, starting whsec_). Verify it before trusting a delivery:
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(secret, timestamp, rawBody, header) {
const expected = "sha256=" + createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
return header.length === expected.length && timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}Not in this version
- No retries. Each event is sent once, with an 8-second timeout; the settings page shows the last status.
creative.renderedis sent for static ads only, not for videos.
Privacy and deletion
Owners can request deletion of their workspace under Settings → Privacy. The request is recorded and emailed to you; the deletion itself is manual. See Workspace deletion requests.