Skip to content
NewMCP server for AI agents — plan and launch campaigns from Claude

API reference · v1

Build on Croud. REST, webhooks and MCP.

Automate the Instagram ads marketplace: review ad requests, launch campaigns, track placements and balances — over REST, signed webhooks, or the Model Context Protocol for AI agents.

https://croud.ai/api/v1Get an API keyOpenAPI 3.1 spec
Guides

Introduction

The API is organized around resources with predictable URLs, JSON bodies and standard HTTP verbs. Every request is scoped to the workspace that owns the API key. Amounts are integer cents, timestamps are ISO 8601 in UTC, and IDs are opaque strings.

Base URL
https://croud.ai/api/v1
MCP endpoint
https://croud.ai/api/mcp

A placement is one creative on one creator account for one campaign. Creators approve, reject or request changes on placements; advertisers launch campaigns, which request placements from every matching account. Every placement has an origin: matched (campaign targeting), open (a creator accepted an open campaign) or direct (the advertiser hand-picked the creator).

Guides

Authentication

Create a key in Settings → Developers → API keys (Starter plan and above). Send it as a Bearer token on every request. Keys start with crd_live_, are shown once, and can be rolled with a grace period.

Request
curl https://croud.ai/api/v1/me \
  -H "Authorization: Bearer crd_live_…"

Keys are scoped. A key never exceeds the role of the member who created it, and stops working if that member leaves. A write scope includes the matching read scope; full-access keys use *.

campaigns:readRead campaigns
campaigns:writeCreate & manage campaigns
creatives:readRead creatives
creatives:writeCreate & manage creatives
accounts:readRead connected accounts
accounts:writeManage account policies
placements:readRead placements
placements:writeApprove / reject placements
personas:readRead personas
personas:writeManage personas
templates:readRead templates & formats
templates:writeCreate, publish & archive caption templates
ai:generateGenerate AI content
analytics:readRead analytics
marketplace:readSearch creator marketplace
wallet:readRead wallet balances & transactions
connections:writeSync & disconnect Instagram accounts
workspace:writeEdit the workspace profile
members:readRead members & invitations
members:writeManage members & invitations
webhooks:writeManage webhook endpoints
payouts:writeRequest & cancel payouts
Guides

Errors

Errors return a non-2xx status and a consistent body. Branch on error.code, show error.message to people.

Response · 403
{
  "error": {
    "code": "forbidden",
    "message": "This API key is missing the required scope: placements:write.",
    "details": {
      "required_scopes": [
        "placements:write"
      ]
    }
  }
}
unauthorized401Missing, malformed, revoked or expired API key.
forbidden403The key lacks a scope, its creator's role lacks the permission, or the workspace is suspended.
not_found404The resource doesn't exist in this workspace (or is outside your teams).
conflict409The resource is in a state that doesn't allow the action, e.g. approving a rejected placement.
invalid_input422Validation failed. details lists each field and message.
feature_unavailable402Your plan doesn't include this feature or format.
plan_limit402A plan limit was reached, e.g. active campaigns.
insufficient_funds402The wallet can't cover the requested budget.
insufficient_credits402Not enough AI credits for the generation.
rate_limited429Too many requests this minute. Wait for Retry-After seconds.
service_unavailable503Scheduled maintenance. Retry after Retry-After seconds.
internal500Something failed on our side. Safe to retry GETs; retry writes after checking state.

Every response includes an X-Request-Id header; include it when contacting support.

Guides

Rate limits

Limits apply per workspace across all keys and both transports, in one-minute windows. Every response reports the current window; when you exceed it you get 429 rate_limited with a Retry-After header.

Headers
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1793180460
Retry-After: 14            # only on 429
Starter60 / min
Pro300 / min
Business1,200 / min
Enterprise6,000 / min
Guides

Idempotency

Send an Idempotency-Key header (any unique string up to 255 characters, e.g. a UUID) on POST, PATCH,PUT and DELETE requests to retry safely. The first response is stored for 24 hours; retries with the same key and the same request return it with Idempotent-Replayed: true. Reusing a key for a different request returns 422 invalid_input; a retry while the original is still running returns 409 conflict. Server errors (5xx) are not stored, so they can be retried with the same key.

Request
curl -X POST https://croud.ai/api/v1/campaigns/cmf0cmp001/launch \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Idempotency-Key: 6f1c2a5e-launch-summer"
Guides

Pagination

List endpoints return newest first with cursor pagination. Pass limit (1–100, default 25) and, for the next page, the previous response's next_cursor as cursor. Stop when has_more is false.

Response
{
  "object": "list",
  "data": [
    "…"
  ],
  "has_more": true,
  "next_cursor": "cmf0plc001"
}
Guides

Open campaigns & direct requests

Besides targeted campaigns, advertisers can run two creator-facing flows. Both depend on the advertiser's plan (open campaigns, direct requests and collab posts are plan features) and use valid keys from reference data for categories and countries.

Open campaignsCreate a campaign with type: "open", an offer_price_cents per post, a budget and an acceptance_mode. At launch the uncommitted budget is held in escrow in the wallet. Creators find it with GET /v1/opportunities and accept with POST /v1/opportunities/{id}/accept: instant campaigns book the slot from escrow right away, review campaigns create an application (pending_advertiser) that the advertiser approves or declines with POST /v1/requests/{id}/review.
Direct requestsCheck the creator with GET /v1/requests/preview, then send POST /v1/requests for a ready creative of a running targeted or direct campaign at your price. The creator approves (POST /v1/placements/{id}/approve), rejects, or counters (POST /v1/placements/{id}/counter), which moves it to pending_advertiser. Answer with POST /v1/requests/{id}/respond: accept books it at the counter price, counter sends a new price back to the creator (pending_approval), decline closes it. Rounds are limited per request; track them in negotiation on the placement.
Collab postsWith collab: true (campaign or request) the post is published as an Instagram collab with your collab_handles invited as collaborators, so it also appears on your profile. Creators opt in per format on their rate cards (collab_enabled) and charge an add-on included in the placement's price_cents (collab_price_cents).
Suggested pricesConnected accounts are analyzed from their recent posts. GET /v1/accounts/{id}/insights returns categories, description, stats and a suggested price per format with its breakdown. Rate cards with pricing_mode: "auto" follow the suggestion.
placement.appliedSent to the advertiser

A creator applied to a review open campaign. Approve or decline with POST /v1/requests/{id}/review.

{"placement_id":"cmf0plc009","campaign_id":"cmf0cmp002","account":"maya.creates","price_cents":30000}
placement.counteredSent to the advertiser

A creator countered your direct request. Answer with POST /v1/requests/{id}/respond.

{"placement_id":"cmf0plc010","account":"techbyleo","offer_cents":60000,"counter_cents":85000}
placement.offer_revisedSent to the creator

The advertiser answered your counter-offer with a new price; the request is waiting for you again.

{"placement_id":"cmf0plc010","account":"techbyleo","counter_cents":85000,"offer_cents":75000}
placement.counter_acceptedSent to the creator

The advertiser accepted your counter-offer; the post is booked and scheduled.

{"placement_id":"cmf0plc010","account":"techbyleo","price_cents":85000,"scheduled_at":"2026-11-05T17:00:00.000Z"}
account.analyzedSent to the creator

Account analysis finished: categories, description, stats and suggested prices were refreshed.

{"account_id":"cmf0acc001","username":"maya.creates","categories":["beauty","lifestyle"],"suggested_categories":["beauty","lifestyle"],"posts_analyzed":15}
Guides

Design studio & brand kits

The design studio turns a template and your brand into finished Instagram graphics. A brand kit holds your colors, fonts, logos and handle. A design template is a slide structure with its own style (carousels, single posts, stories). A design is your copy of a template with your brand applied: its slides are written by you or by AI from a brief, then exported to images or saved straight into a creative.

ScopesReads use creatives:read, changes creatives:write. Writing with AI (brief on create, or POST /v1/designs/{id}/generate) also needs ai:generate and uses AI credits. Saving to the media library is part of creatives:write.
Templates & plansGET /v1/design-templates lists every template with its availability after platform, plan and workspace controls. Templates above your plan are listed with available: false and only their first slides; creating a design from one returns 402 feature_unavailable. Designs made from a template your plan no longer includes export with a watermark. Saved designs, brand kits, custom templates and monthly exports are plan limits.
Slidesslides and style are design documents and keep the engine's camelCase keys so they round-trip unchanged. Each slide is { id, layout, variant?, content }; GET /v1/layouts lists every layout's content fields and soft character limits. Send expected_updated_at with edits to avoid overwriting a teammate (409 conflict).
ExportsExports render in headless Chromium to PNG, JPG, a ZIP of images or a PDF. Most finish inside the request (status: done); on deployments with a render worker they return queued: poll GET /v1/designs/{id}/exports/{export_id}, pass wait: true, or listen for design.exported. Files not saved to the media library are deleted after 7 days.
Design → export → creative
# 1. Create a design from a template with your brand kit; AI writes the slides
curl -X POST https://croud.ai/api/v1/designs \
  -H "Authorization: Bearer $CROUD_API_KEY" -H "Content-Type: application/json" \
  -d '{ "template_id": "cmf0dt0001", "campaign_id": "cmf0cmp001",
        "brief": "Three myths about niacinamide, for people new to skincare." }'

# 2. Render it to PNGs (or "zip", "pdf"), waiting for the result
curl -X POST https://croud.ai/api/v1/designs/cmf0dsn001/exports \
  -H "Authorization: Bearer $CROUD_API_KEY" -H "Content-Type: application/json" \
  -d '{ "kind": "png", "wait": true }'

# 3. Or turn it straight into a draft carousel creative for the campaign
curl -X POST https://croud.ai/api/v1/designs/cmf0dsn001/creative \
  -H "Authorization: Bearer $CROUD_API_KEY"
brand_kit.createdSent to the advertiser

A brand kit was created (the first kit becomes the default).

{"brand_kit_id":"cmf0bk0001","name":"Lumen","is_default":true}
brand_kit.updatedSent to the advertiser

A brand kit's colors, fonts, logos or details changed. Designs pick it up on their next render.

{"brand_kit_id":"cmf0bk0001","name":"Lumen"}
design.createdSent to the advertiser

A design was created from a template, duplicated, or generated for a unique post (template is the template key or duplicate).

{"design_id":"cmf0dsn001","name":"Myth vs fact: niacinamide","template":"myth-vs-fact","campaign_id":"cmf0cmp001"}
design.exportedSent to the advertiser

An export finished rendering. File URLs expire after 7 days unless they were saved to the media library (media_id).

{"design_id":"cmf0dsn001","export_id":"cmf0dex001","kind":"png","files":[{"url":"https://croud.ai/uploads/ws/slide-1.png","media_id":null}]}
Guides

Unique posts per creator

Instagram ranks original content higher and groups near-identical ads together. With unique posts on, a campaign writes a different post for every creator: its own messaging angle, caption and (for image formats) design, written for that creator's audience, while your locked elements never change. The plan feature is creativeVariants; writing uses the advertiser's AI credits.

Turn on unique posts
curl -X PATCH https://croud.ai/api/v1/campaigns/cmf0cmp001 \
  -H "Authorization: Bearer $CROUD_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "brand_kit_id": "cmf0bk0001",
    "variants_enabled": true,
    "variant_config": {
      "angles": ["routine", "myth_busting", "review"],
      "design_template_ids": ["cmf0dt0001", "cmf0dt0002"],
      "brief": "Glow serum: 10% niacinamide, fragrance-free, $34. Launches Nov 1.",
      "must_include": { "hashtags": ["ad"], "mentions": ["lumen.skincare"],
                        "cta": "Shop the launch", "claims": ["Fragrance-free"] },
      "avoid": ["cure", "miracle"],
      "review": "review"
    }
  }'
AssignmentEach creator gets a combination of angle, design template and caption template. Combinations rotate: no angle and template pair repeats until every pair has been used, and among equally used options the angle that suits the creator's content categories wins. Angles come from the creative_angle list (GET /v1/reference/creative_angle); angles blocked for the campaign's ad category (e.g. before/after for health) are never used. Design templates apply to feed images, carousels and stories; video formats keep the base creative's media and vary the caption.
UniquenessEvery caption is compared with the campaign's other posts (shared three-word phrases). Above 35% overlap it is rewritten, up to 3 attempts, and the least similar version is kept. The score is returned as generation.similarity (0–1) on each variant. A campaign writes at most 500 posts; later placements get the base creative.
ReviewNew placements start in drafting (pending_status is where they go next) while the post is written. With review: "review" the variant waits as awaiting_review: approve it (POST /v1/variants/{id}/approve or all at once), edit it, rewrite it with another angle or notes, or send the base creative instead. Approved posts continue to the creator's normal review, or are scheduled for accepted open-campaign slots. Creators see creative: null while a placement is drafting. With review: "auto" posts go out as soon as they're written.
Locked elementsmust_include hashtags, mentions and CTA are added to every post, and the link stays the base creative's. Product claims are limited to the brief and the approved claims; avoid words, the creator's blocked keywords and the persona's banned words are never used. Ad disclosure is added at publishing as for every placement.
FallbacksCreators whose policy doesn't allow AI-generated content receive the base creative. If a post can't be written (no credits, provider error) the base creative is sent when fallback_to_base is on (default); otherwise a failed variant waits for you to edit or rewrite it.
creative.variant_readySent to the advertiser

A creator's unique post was written (or rewritten). With review: true it waits for your approval; otherwise it was sent on. similarity is the highest caption overlap with another creator's post (0–1).

{"creative_id":"cmf0crt101","placement_id":"cmf0plc001","account":"maya.creates","angle":"routine","similarity":0.12,"review":true}
creative.variant_failedSent to the advertiser

A unique post couldn't be written and the campaign doesn't fall back to the base creative. Edit it (PATCH /v1/variants/{id}) or rewrite it to continue.

{"creative_id":"cmf0crt102","placement_id":"cmf0plc002","account":"techbyleo","reason":"Not enough AI credits"}
Reference

Workspace

The workspace behind the API key, its plan and usage.

GET/v1/me

Get the authenticated workspace

Returns the workspace (its profile and the sides it runs: creator, advertiser or both; edit the profile with PATCH /v1/workspace), plan, limits and feature flags the API key belongs to, plus the key's scopes and effective permissions: the scopes' permissions, limited to the creating member's role and to the workspace's sides. Endpoints of a side the workspace doesn't run return 403. Use it to verify a key.

Scopeany keyMCP toolwhoami
Request
curl "https://croud.ai/api/v1/me" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "workspace_identity",
  "workspace": {
    "id": "cmf0ws0001",
    "name": "Lumen Skincare",
    "slug": "lumen-skincare",
    "creator_enabled": false,
    "advertiser_enabled": true,
    "sides": [
      "advertiser"
    ],
    "currency": "USD",
    "timezone": "America/New_York",
    "logo_url": "https://lumen.example/logo.png",
    "website": "https://lumen.example",
    "instagram_handle": "lumen.skincare",
    "description": "Science-backed skincare without the jargon.",
    "industry": "beauty",
    "country": "US"
  },
  "plan": {
    "key": "pro",
    "name": "Pro"
  },
  "api_key": {
    "id": "cmf0key001",
    "name": "Production",
    "prefix": "crd_live_8fQ2",
    "scopes": [
      "placements:read",
      "placements:write"
    ],
    "expires_at": null
  },
  "permissions": [
    "accounts.read",
    "campaigns.read",
    "placements.review"
  ],
  "features": {
    "api": true,
    "mcp": true,
    "webhooks": true
  },
  "limits": {
    "api_requests_per_minute": 300,
    "webhook_endpoints": 10,
    "active_campaigns": 50
  }
}
GET/v1/usage

Get usage and AI credits

AI credit balance and metered usage (API requests, MCP tool calls, AI generations) for the current billing period. Limits of -1 mean unlimited.

Scopeany keyMCP toolget_usage
Request
curl "https://croud.ai/api/v1/usage" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "usage",
  "period": "2026-10",
  "ai_credits": {
    "balance": 2840,
    "monthly_allowance": 3000
  },
  "metrics": {
    "api_requests": 1204,
    "mcp_calls": 87,
    "ai_generations": 160
  },
  "limits": {
    "api_requests_per_minute": 300
  }
}
GET/v1/workspace

Get the workspace profile

The workspace's profile: name, logo, website, Instagram username, description, industry, country and time zone, plus the sides it runs.

Scopeany keyMCP toolget_workspace
Request
curl "https://croud.ai/api/v1/workspace" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0ws0001",
  "object": "workspace",
  "name": "Lumen Skincare",
  "slug": "lumen-skincare",
  "logo_url": "https://lumen.example/logo.png",
  "website": "https://lumen.example",
  "instagram_handle": "lumen.skincare",
  "description": "Science-backed skincare without the jargon.",
  "industry": "beauty",
  "country": "US",
  "timezone": "America/New_York",
  "creator_enabled": false,
  "advertiser_enabled": true,
  "sides": [
    "advertiser"
  ],
  "created_at": "2026-09-01T10:00:00.000Z"
}
PATCH/v1/workspace

Update the workspace profile

Update profile fields; omitted fields keep their values and null or "" clears one (the name can't be cleared). industry is an ad_category key and country a country key (see GET /v1/reference/{list}). The Instagram username is invited as collaborator on collab posts. The URL, sides and billing stay in the app.

Scopeworkspace:writeMCP toolupdate_workspace
Body
name
string
logo_url
string | nullhttps:// image URL or a media library path (/uploads/…)
website
string | nullhttps:// URL
instagram_handle
string | nullInstagram username, with or without @
description
string | null
industry
string | nullad_category reference key
country
string | nullISO country code (country reference key)
timezone
stringIANA time zone, e.g. Europe/Paris
Request
curl -X PATCH "https://croud.ai/api/v1/workspace" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"website":"https://lumen.example","instagram_handle":"lumen.skincare","timezone":"America/New_York"}'
Response · 200
{
  "id": "cmf0ws0001",
  "object": "workspace",
  "name": "Lumen Skincare",
  "slug": "lumen-skincare",
  "logo_url": "https://lumen.example/logo.png",
  "website": "https://lumen.example",
  "instagram_handle": "lumen.skincare",
  "description": "Science-backed skincare without the jargon.",
  "industry": "beauty",
  "country": "US",
  "timezone": "America/New_York",
  "creator_enabled": false,
  "advertiser_enabled": true,
  "sides": [
    "advertiser"
  ],
  "created_at": "2026-09-01T10:00:00.000Z"
}
Reference

Members

The workspace's members and invitations.

GET/v1/members

List members

Everyone in the workspace with their role, access scope, teams and status, oldest first.

Scopemembers:readMCP toollist_members
Query parameters
limit
integerPage size, 1–100 (default 25)
cursor
stringnext_cursor from the previous page
Request
curl "https://croud.ai/api/v1/members" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0mem001",
      "object": "member",
      "user_id": "cmf0usr001",
      "name": "Jordan Lee",
      "email": "jordan@lumen.example",
      "role": {
        "id": "cmf0rol001",
        "key": "admin",
        "name": "Admin",
        "is_system": true,
        "is_owner": false
      },
      "access_scope": "all",
      "status": "active",
      "teams": [],
      "two_factor_enabled": true,
      "joined_at": "2026-09-01T10:00:00.000Z",
      "last_active_at": "2026-10-30T08:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
GET/v1/invitations

List invitations

Pending and expired invitations, newest first. Pending invitations count toward the plan's seats.

Scopemembers:readMCP toollist_invitations
Query parameters
limit
integerPage size, 1–100 (default 25)
cursor
stringnext_cursor from the previous page
Request
curl "https://croud.ai/api/v1/invitations" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0inv001",
      "object": "invitation",
      "email": "sam@lumen.example",
      "role": {
        "id": "cmf0rol003",
        "name": "Member"
      },
      "status": "pending",
      "access_scope": "all",
      "teams": [],
      "invited_by": "Jordan Lee",
      "expires_at": "2026-11-08T10:00:00.000Z",
      "created_at": "2026-11-01T10:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
POST/v1/invitations

Invite members

Emails an invitation to each address (up to 50). Re-inviting a pending address replaces its invitation. You can only grant roles whose permissions the key's creator holds; custom roles and team-scoped access depend on the plan. If the key's creator is team-scoped, invitations must use access_scope: teams with teams they belong to. Invitees must sign in with the invited email, and it must be verified, to join.

Scopemembers:writeMCP toolinvite_members
Body
emailsrequired
string[]
rolerequired
stringSystem role key (admin, manager, member, billing, viewer) or a custom role id
access_scope
"all" | "teams"teams: only the teams in team_ids (plan feature)
team_ids
string[]
Request
curl -X POST "https://croud.ai/api/v1/invitations" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"emails":["sam@lumen.example"],"role":"member"}'
Response · 201
{
  "object": "list",
  "data": [
    {
      "id": "cmf0inv001",
      "object": "invitation",
      "email": "sam@lumen.example",
      "role": {
        "id": "cmf0rol003",
        "name": "Member"
      },
      "status": "pending",
      "access_scope": "all",
      "teams": [],
      "invited_by": "Jordan Lee",
      "expires_at": "2026-11-08T10:00:00.000Z",
      "created_at": "2026-11-01T10:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
POST/v1/invitations/{id}/resend

Resend an invitation

Emails a pending or expired invitation again with a fresh link, valid for another 7 days. Earlier links stop working. Re-activating an expired invitation needs a free seat; you can only resend invitations for roles you could grant.

Scopemembers:writeMCP toolresend_invitation
Path parameters
idrequired
stringInvitation ID
Request
curl -X POST "https://croud.ai/api/v1/invitations/id_123/resend" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0inv001",
  "object": "invitation",
  "email": "sam@lumen.example",
  "role": {
    "id": "cmf0rol003",
    "name": "Member"
  },
  "status": "pending",
  "access_scope": "all",
  "teams": [],
  "invited_by": "Jordan Lee",
  "expires_at": "2026-11-08T10:00:00.000Z",
  "created_at": "2026-11-01T10:00:00.000Z"
}
DELETE/v1/invitations/{id}

Revoke an invitation

Cancels a pending or expired invitation: its link stops working and the seat is freed. Accepted invitations can't be revoked; remove the member instead.

Scopemembers:writeMCP toolrevoke_invitation
Path parameters
idrequired
stringInvitation ID
Request
curl -X DELETE "https://croud.ai/api/v1/invitations/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0inv001",
  "object": "invitation",
  "revoked": true
}
PATCH/v1/members/{id}

Update a member

Change a member's role, access scope or teams. Omitted fields keep their values. You can only grant roles whose permissions the key's creator holds; owners' access can only be changed in the app, by another owner. A key can't change its own creator's membership.

Scopemembers:writeMCP toolupdate_member
Path parameters
idrequired
stringMember ID
Body
role
stringSystem role key (admin, manager, member, billing, viewer) or a custom role id
access_scope
"all" | "teams"teams: only the teams in team_ids (plan feature)
team_ids
string[]
Request
curl -X PATCH "https://croud.ai/api/v1/members/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"role":"manager"}'
Response · 200
{
  "id": "cmf0mem001",
  "object": "member",
  "user_id": "cmf0usr001",
  "name": "Jordan Lee",
  "email": "jordan@lumen.example",
  "role": {
    "id": "cmf0rol002",
    "key": "manager",
    "name": "Manager",
    "is_system": true,
    "is_owner": false
  },
  "access_scope": "all",
  "status": "active",
  "teams": [],
  "two_factor_enabled": true,
  "joined_at": "2026-09-01T10:00:00.000Z",
  "last_active_at": "2026-10-30T08:00:00.000Z"
}
DELETE/v1/members/{id}

Remove a member

Removes someone from the workspace: they lose access immediately and API keys they created are revoked. The last owner can't be removed, owners can only be removed in the app by another owner, and a key can't remove its own creator.

Scopemembers:writeMCP toolremove_member
Path parameters
idrequired
stringMember ID
Request
curl -X DELETE "https://croud.ai/api/v1/members/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0mem001",
  "object": "member",
  "deleted": true
}
Reference

Webhooks

Endpoints that receive signed events (placements, campaigns, payouts…) as they happen.

GET/v1/webhooks

List webhook endpoints

Webhook endpoints with their subscribed events and the last 7 days of delivery counts. Secrets are never returned here.

Scopewebhooks:writeMCP toollist_webhooks
Query parameters
limit
integerPage size, 1–100 (default 25)
cursor
stringnext_cursor from the previous page
Request
curl "https://croud.ai/api/v1/webhooks" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0whk001",
      "object": "webhook_endpoint",
      "url": "https://hooks.lumen.example/croud",
      "description": "Placement updates",
      "events": [
        "placement.approved",
        "placement.published"
      ],
      "enabled": true,
      "failure_count": 0,
      "created_at": "2026-10-01T10:00:00.000Z",
      "updated_at": "2026-10-01T10:00:00.000Z",
      "stats_7d": {
        "succeeded": 42,
        "failed": 0,
        "pending": 1
      }
    }
  ],
  "has_more": false,
  "next_cursor": null
}
POST/v1/webhooks

Create a webhook endpoint

Registers an https:// endpoint for the given events. The signing secret is returned once, in this response: verify the Croud-Signature header with it. Plan feature webhooks; counts toward the plan's endpoint limit.

Scopewebhooks:writeMCP toolcreate_webhook
Body
urlrequired
stringhttps:// URL that receives POSTed events
description
string
eventsrequired
string[]Event types to receive, or ["*"] for every event (events of a side the workspace doesn't run are refused)
Request
curl -X POST "https://croud.ai/api/v1/webhooks" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://hooks.lumen.example/croud","events":["placement.approved","placement.published"],"description":"Placement updates"}'
Response · 201
{
  "id": "cmf0whk001",
  "object": "webhook_endpoint",
  "url": "https://hooks.lumen.example/croud",
  "description": "Placement updates",
  "events": [
    "placement.approved",
    "placement.published"
  ],
  "enabled": true,
  "failure_count": 0,
  "created_at": "2026-10-01T10:00:00.000Z",
  "updated_at": "2026-10-01T10:00:00.000Z",
  "secret": "whsec_8fQ2…"
}
GET/v1/webhooks/{id}

Get a webhook endpoint

One webhook endpoint (without its secret).

Scopewebhooks:writeMCP toolget_webhook
Path parameters
idrequired
stringWebhook endpoint ID
Request
curl "https://croud.ai/api/v1/webhooks/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0whk001",
  "object": "webhook_endpoint",
  "url": "https://hooks.lumen.example/croud",
  "description": "Placement updates",
  "events": [
    "placement.approved",
    "placement.published"
  ],
  "enabled": true,
  "failure_count": 0,
  "created_at": "2026-10-01T10:00:00.000Z",
  "updated_at": "2026-10-01T10:00:00.000Z"
}
PATCH/v1/webhooks/{id}

Update a webhook endpoint

Change the URL, description or events, or turn the endpoint on or off (enabled). Turning it back on resets the failure count. Omitted fields keep their values.

Scopewebhooks:writeMCP toolupdate_webhook
Path parameters
idrequired
stringWebhook endpoint ID
Body
url
string
description
string
events
string[]Event types to receive, or ["*"] for every event (events of a side the workspace doesn't run are refused)
enabled
boolean
Request
curl -X PATCH "https://croud.ai/api/v1/webhooks/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"events":["*"],"enabled":true}'
Response · 200
{
  "id": "cmf0whk001",
  "object": "webhook_endpoint",
  "url": "https://hooks.lumen.example/croud",
  "description": "Placement updates",
  "events": [
    "*"
  ],
  "enabled": true,
  "failure_count": 0,
  "created_at": "2026-10-01T10:00:00.000Z",
  "updated_at": "2026-10-01T10:00:00.000Z"
}
DELETE/v1/webhooks/{id}

Delete a webhook endpoint

Deletes the endpoint and its delivery history. Pending retries are dropped.

Scopewebhooks:writeMCP tooldelete_webhook
Path parameters
idrequired
stringWebhook endpoint ID
Request
curl -X DELETE "https://croud.ai/api/v1/webhooks/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0whk001",
  "object": "webhook_endpoint",
  "deleted": true
}
POST/v1/webhooks/{id}/test

Send a test event

Sends a signed webhook.test event to the endpoint now and returns the outcome. Test deliveries aren't retried and don't count toward auto-disable.

Scopewebhooks:writeMCP tooltest_webhook
Path parameters
idrequired
stringWebhook endpoint ID
Request
curl -X POST "https://croud.ai/api/v1/webhooks/id_123/test" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "webhook_test",
  "delivery_id": "cmf0dlv001",
  "ok": true,
  "status": 200,
  "error": null,
  "duration_ms": 182
}
Reference

Catalog

Ad formats and caption templates, with plan and workspace availability applied. Create and publish your own templates.

GET/v1/formats

List ad formats

Every ad format with its effective availability for this workspace after platform, plan and workspace controls. can_launch is false for draft_only and disabled formats.

Scopetemplates:readMCP toollist_formats
Query parameters
platform
"instagram"Filter by platform
Request
curl "https://croud.ai/api/v1/formats" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "key": "ig_reel",
      "object": "format",
      "platform": "instagram",
      "name": "Reel",
      "description": "Vertical video up to 90s",
      "specs": {
        "mediaTypes": [
          "video"
        ],
        "aspectRatios": [
          "9:16"
        ]
      },
      "availability": "enabled",
      "can_launch": true,
      "restricted_by": null,
      "reason": null
    }
  ],
  "has_more": false,
  "next_cursor": null
}
GET/v1/templates

List templates

Platform and workspace templates visible to this workspace, each with its effective availability. Hidden templates are omitted.

Scopetemplates:readMCP toollist_templates
Query parameters
format
stringFilter by format key, e.g. ig_reel
source
"platform" | "workspace"Only platform or only workspace templates
category
stringFilter by content type key (see GET /v1/reference/content_type), e.g. product_launch
search
stringCase-insensitive match on name and description
Request
curl "https://croud.ai/api/v1/templates" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0tpl001",
      "object": "template",
      "source": "platform",
      "platform": "instagram",
      "format": "ig_carousel",
      "name": "Product launch carousel",
      "description": "Five-slide launch story",
      "category": "product_launch",
      "status": "published",
      "min_plan": null,
      "content": {
        "captionTemplate": "Meet {{product}}…",
        "hashtags": [
          "#launch"
        ]
      },
      "thumbnail_url": null,
      "tags": [],
      "version": 3,
      "availability": "enabled",
      "reason": null,
      "updated_at": "2026-10-01T09:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
GET/v1/templates/{id}

Get a template

One platform or workspace template with its availability. editable is true for the workspace's own templates.

Scopetemplates:readMCP toolget_template
Path parameters
idrequired
stringTemplate ID
Request
curl "https://croud.ai/api/v1/templates/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0tpl009",
  "object": "template",
  "source": "workspace",
  "platform": "instagram",
  "format": "ig_carousel",
  "name": "Launch carousel",
  "description": "Five slides: hook, problem, product, proof, offer",
  "category": "product_launch",
  "status": "draft",
  "min_plan": null,
  "content": {
    "captionTemplate": "Meet {{product}}. {{benefit}}",
    "hashtags": [
      "launch"
    ],
    "cta": "Shop now",
    "variables": [
      {
        "key": "product",
        "label": "Product",
        "default": ""
      },
      {
        "key": "benefit",
        "label": "Benefit",
        "default": ""
      }
    ]
  },
  "thumbnail_url": null,
  "tags": [
    "launch"
  ],
  "version": 1,
  "availability": "draft_only",
  "reason": null,
  "updated_at": "2026-11-01T10:00:00.000Z",
  "editable": true
}
POST/v1/templates

Create a template

Creates a workspace caption template as a draft (or published right away). Counts toward the plan's template limit. Use {{variables}} in the caption; POST /v1/creatives/render-template fills them.

Scopetemplates:writeMCP toolcreate_template
Body
namerequired
string
description
string | null
formatrequired
stringFormat key, e.g. ig_carousel (see GET /v1/formats)
category
string | nullcontent_type reference key
tags
string[]
contentrequired
objectCaption structure, hashtags, CTA and media guidance
status
"draft" | "published"
Request
curl -X POST "https://croud.ai/api/v1/templates" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Launch carousel","format":"ig_carousel","category":"product_launch","content":{"caption_template":"Meet {{product}}. {{benefit}}","hashtags":["launch"],"cta":"Shop now"}}'
Response · 201
{
  "id": "cmf0tpl009",
  "object": "template",
  "source": "workspace",
  "platform": "instagram",
  "format": "ig_carousel",
  "name": "Launch carousel",
  "description": "Five slides: hook, problem, product, proof, offer",
  "category": "product_launch",
  "status": "draft",
  "min_plan": null,
  "content": {
    "captionTemplate": "Meet {{product}}. {{benefit}}",
    "hashtags": [
      "launch"
    ],
    "cta": "Shop now",
    "variables": [
      {
        "key": "product",
        "label": "Product",
        "default": ""
      },
      {
        "key": "benefit",
        "label": "Benefit",
        "default": ""
      }
    ]
  },
  "thumbnail_url": null,
  "tags": [
    "launch"
  ],
  "version": 1,
  "availability": "draft_only",
  "reason": null,
  "updated_at": "2026-11-01T10:00:00.000Z",
  "editable": true
}
PATCH/v1/templates/{id}

Update a template

Edit a workspace template; omitted fields keep their values. Content changes create a new version. Platform templates are read-only: duplicate one in the app to edit it.

Scopetemplates:writeMCP toolupdate_template
Path parameters
idrequired
stringTemplate ID
Body
name
string
description
string | null
format
stringFormat key, e.g. ig_carousel (see GET /v1/formats)
category
string | nullcontent_type reference key
tags
string[]
content
objectCaption structure, hashtags, CTA and media guidance
Request
curl -X PATCH "https://croud.ai/api/v1/templates/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Launch carousel v2","content":{"caption_template":"{{product}} is here. {{benefit}}"}}'
Response · 200
{
  "id": "cmf0tpl009",
  "object": "template",
  "source": "workspace",
  "platform": "instagram",
  "format": "ig_carousel",
  "name": "Launch carousel",
  "description": "Five slides: hook, problem, product, proof, offer",
  "category": "product_launch",
  "status": "draft",
  "min_plan": null,
  "content": {
    "captionTemplate": "Meet {{product}}. {{benefit}}",
    "hashtags": [
      "launch"
    ],
    "cta": "Shop now",
    "variables": [
      {
        "key": "product",
        "label": "Product",
        "default": ""
      },
      {
        "key": "benefit",
        "label": "Benefit",
        "default": ""
      }
    ]
  },
  "thumbnail_url": null,
  "tags": [
    "launch"
  ],
  "version": 2,
  "availability": "draft_only",
  "reason": null,
  "updated_at": "2026-11-01T10:00:00.000Z",
  "editable": true
}
POST/v1/templates/{id}/publish

Publish a template

Makes a workspace template available for creatives (from draft, or restores an archived one). The format must be enabled for the workspace.

Scopetemplates:writeMCP toolpublish_template
Path parameters
idrequired
stringTemplate ID
Request
curl -X POST "https://croud.ai/api/v1/templates/id_123/publish" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0tpl009",
  "object": "template",
  "source": "workspace",
  "platform": "instagram",
  "format": "ig_carousel",
  "name": "Launch carousel",
  "description": "Five slides: hook, problem, product, proof, offer",
  "category": "product_launch",
  "status": "published",
  "min_plan": null,
  "content": {
    "captionTemplate": "Meet {{product}}. {{benefit}}",
    "hashtags": [
      "launch"
    ],
    "cta": "Shop now",
    "variables": [
      {
        "key": "product",
        "label": "Product",
        "default": ""
      },
      {
        "key": "benefit",
        "label": "Benefit",
        "default": ""
      }
    ]
  },
  "thumbnail_url": null,
  "tags": [
    "launch"
  ],
  "version": 1,
  "availability": "enabled",
  "reason": null,
  "updated_at": "2026-11-01T10:00:00.000Z",
  "editable": true
}
POST/v1/templates/{id}/unpublish

Move a template back to draft

Turns a published or archived workspace template back into a draft.

Scopetemplates:writeMCP toolunpublish_template
Path parameters
idrequired
stringTemplate ID
Request
curl -X POST "https://croud.ai/api/v1/templates/id_123/unpublish" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0tpl009",
  "object": "template",
  "source": "workspace",
  "platform": "instagram",
  "format": "ig_carousel",
  "name": "Launch carousel",
  "description": "Five slides: hook, problem, product, proof, offer",
  "category": "product_launch",
  "status": "draft",
  "min_plan": null,
  "content": {
    "captionTemplate": "Meet {{product}}. {{benefit}}",
    "hashtags": [
      "launch"
    ],
    "cta": "Shop now",
    "variables": [
      {
        "key": "product",
        "label": "Product",
        "default": ""
      },
      {
        "key": "benefit",
        "label": "Benefit",
        "default": ""
      }
    ]
  },
  "thumbnail_url": null,
  "tags": [
    "launch"
  ],
  "version": 1,
  "availability": "draft_only",
  "reason": null,
  "updated_at": "2026-11-01T10:00:00.000Z",
  "editable": true
}
POST/v1/templates/{id}/archive

Archive a template

Hides a workspace template from pickers. Creatives that used it keep their content. Archived templates can be published again or deleted.

Scopetemplates:writeMCP toolarchive_template
Path parameters
idrequired
stringTemplate ID
Request
curl -X POST "https://croud.ai/api/v1/templates/id_123/archive" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0tpl009",
  "object": "template",
  "source": "workspace",
  "platform": "instagram",
  "format": "ig_carousel",
  "name": "Launch carousel",
  "description": "Five slides: hook, problem, product, proof, offer",
  "category": "product_launch",
  "status": "archived",
  "min_plan": null,
  "content": {
    "captionTemplate": "Meet {{product}}. {{benefit}}",
    "hashtags": [
      "launch"
    ],
    "cta": "Shop now",
    "variables": [
      {
        "key": "product",
        "label": "Product",
        "default": ""
      },
      {
        "key": "benefit",
        "label": "Benefit",
        "default": ""
      }
    ]
  },
  "thumbnail_url": null,
  "tags": [
    "launch"
  ],
  "version": 1,
  "availability": "hidden",
  "reason": null,
  "updated_at": "2026-11-01T10:00:00.000Z",
  "editable": true
}
DELETE/v1/templates/{id}

Delete a template

Permanently deletes an archived workspace template and its versions.

Scopetemplates:writeMCP tooldelete_template
Path parameters
idrequired
stringTemplate ID
Request
curl -X DELETE "https://croud.ai/api/v1/templates/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0tpl009",
  "object": "template",
  "deleted": true
}
Reference

Campaigns

Advertiser campaigns: create, edit, launch, pause and preview matching creators.

GET/v1/campaigns

List campaigns

Campaigns in the workspace (team-scoped keys only see their teams'), most recently updated first. Archived campaigns are excluded unless status=archived or status=all.

Scopecampaigns:readMCP toollist_campaigns
Query parameters
limit
integerPage size, 1–100 (default 25)
cursor
stringnext_cursor from the previous page
status
"draft" | "pending_review" | "scheduled" | "active" | "paused" | "completed" | "canceled" | "archived" | "all" | "live"A status, live (active, scheduled, pending review) or all
team_id
string
search
stringMatch on campaign name
Request
curl "https://croud.ai/api/v1/campaigns" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0cmp001",
      "object": "campaign",
      "name": "Autumn glow launch",
      "description": "Serum launch with mid-tier beauty creators",
      "type": "targeted",
      "objective": "launch",
      "category": "beauty",
      "status": "active",
      "offer_price_cents": null,
      "acceptance_mode": "instant",
      "collab": false,
      "collab_handles": [
        "lumen.skincare"
      ],
      "team_id": null,
      "persona_id": null,
      "budget_cents": 500000,
      "committed_cents": 0,
      "spent_cents": 0,
      "currency": "USD",
      "max_price_per_post_cents": 60000,
      "start_date": "2026-11-01T00:00:00.000Z",
      "end_date": "2026-11-30T00:00:00.000Z",
      "targeting": {
        "niches": [
          "beauty"
        ],
        "countries": [
          "US"
        ],
        "min_followers": 10000
      },
      "brand_safety": {},
      "landing_url": "https://lumen.example/serum",
      "utm": null,
      "brand_kit_id": "cmf0bk0001",
      "variants_enabled": true,
      "variant_config": {
        "angles": [
          "tutorial",
          "routine",
          "review"
        ],
        "design_template_ids": [
          "cmf0dt0001",
          "cmf0dt0002"
        ],
        "caption_template_ids": [],
        "brief": "Glow serum: 10% niacinamide, fragrance-free, $34. Launching November 1.",
        "must_include": {
          "hashtags": [
            "ad",
            "lumenglow"
          ],
          "mentions": [
            "lumen.skincare"
          ],
          "cta": "Shop the launch",
          "claims": [
            "Fragrance-free"
          ]
        },
        "avoid": [
          "cure",
          "miracle"
        ],
        "tailor_to_creator": true,
        "review": "review",
        "fallback_to_base": true,
        "slide_count": 5
      },
      "launched_at": null,
      "completed_at": null,
      "created_at": "2026-10-20T10:00:00.000Z",
      "updated_at": "2026-10-28T10:00:00.000Z",
      "placement_count": 6,
      "live_placements": 2,
      "reach": 81200,
      "impressions": 120400,
      "creative_count": 2
    }
  ],
  "has_more": false,
  "next_cursor": null,
  "total": 1
}
POST/v1/campaigns

Create a campaign

Creates a draft campaign. Add creatives, set a budget and launch it when ready. type picks how creators are reached: targeted (matched requests), open (an offer creators accept; the budget is escrowed at launch) or direct (hand-picked requests). Open campaigns, direct requests and collab posts depend on your plan. Audience demographics and hand-picked accounts require advanced targeting. The whole body is validated before anything is saved: if any field is rejected, no draft is created.

Scopecampaigns:writeMCP toolcreate_campaign
Body
namerequired
string
type
"targeted" | "open" | "direct"targeted (default): requests go to matching creators at their rates. open: you set offer_price_cents and creators accept from their account. direct: you send hand-picked creators requests (POST /v1/requests). Can only change while a draft.
objectiverequired
stringawareness | engagement | traffic | conversions | launch
categoryrequired
stringAd category used for creator policy matching, e.g. beauty
description
string | null
landing_url
string | nullhttps:// URL
team_id
string | null
persona_id
string | nullBrand voice for AI-generated copy
budget_cents
integer
max_price_per_post_cents
integer | null
offer_price_cents
integer | nullOpen campaigns: price per post offered to every creator (at least the platform minimum)
acceptance_mode
"instant" | "review"Open campaigns: instant books the slot when a creator accepts; review creates an application you approve or decline
collab
booleanPosts are Instagram collab posts with your brand as collaborator (plan-gated)
collab_handles
string[]Instagram usernames invited as collaborators (max 3)
start_date
string | nullISO date or datetime; null = start at launch
end_date
string | nullISO date or datetime; null = run until budget is spent
targeting
objectWhich creator accounts the campaign matches
brand_kit_id
string | nullBrand kit for designs and unique-post visuals (defaults to the workspace's default kit)
variants_enabled
booleanWrite a unique post for every creator (plan feature creativeVariants; needs variant_config)
variant_config
object | null
Request
curl -X POST "https://croud.ai/api/v1/campaigns" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Autumn glow launch","objective":"launch","category":"beauty","budget_cents":500000,"max_price_per_post_cents":60000,"start_date":"2026-11-01","end_date":"2026-11-30","landing_url":"https://lumen.example/serum","targeting":{"niches":["beauty"],"countries":["US"],"min_followers":10000}}'
Response · 201
{
  "id": "cmf0cmp001",
  "object": "campaign",
  "name": "Autumn glow launch",
  "description": "Serum launch with mid-tier beauty creators",
  "type": "targeted",
  "objective": "launch",
  "category": "beauty",
  "status": "active",
  "offer_price_cents": null,
  "acceptance_mode": "instant",
  "collab": false,
  "collab_handles": [
    "lumen.skincare"
  ],
  "team_id": null,
  "persona_id": null,
  "budget_cents": 500000,
  "committed_cents": 0,
  "spent_cents": 0,
  "currency": "USD",
  "max_price_per_post_cents": 60000,
  "start_date": "2026-11-01T00:00:00.000Z",
  "end_date": "2026-11-30T00:00:00.000Z",
  "targeting": {
    "niches": [
      "beauty"
    ],
    "countries": [
      "US"
    ],
    "min_followers": 10000
  },
  "brand_safety": {},
  "landing_url": "https://lumen.example/serum",
  "utm": null,
  "brand_kit_id": "cmf0bk0001",
  "variants_enabled": true,
  "variant_config": {
    "angles": [
      "tutorial",
      "routine",
      "review"
    ],
    "design_template_ids": [
      "cmf0dt0001",
      "cmf0dt0002"
    ],
    "caption_template_ids": [],
    "brief": "Glow serum: 10% niacinamide, fragrance-free, $34. Launching November 1.",
    "must_include": {
      "hashtags": [
        "ad",
        "lumenglow"
      ],
      "mentions": [
        "lumen.skincare"
      ],
      "cta": "Shop the launch",
      "claims": [
        "Fragrance-free"
      ]
    },
    "avoid": [
      "cure",
      "miracle"
    ],
    "tailor_to_creator": true,
    "review": "review",
    "fallback_to_base": true,
    "slide_count": 5
  },
  "launched_at": null,
  "completed_at": null,
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z",
  "team": null,
  "persona": null,
  "creatives": [],
  "placements": [
    {
      "id": "cmf0plc001",
      "status": "scheduled",
      "origin": "matched",
      "is_collab": false,
      "price_cents": 45000,
      "account": {
        "id": "cmf0acc001",
        "username": "maya.creates",
        "followers": 48200
      },
      "creative": {
        "id": "cmf0crt001",
        "name": "Serum reel",
        "format": "ig_reel"
      },
      "scheduled_at": "2026-11-02T15:00:00.000Z",
      "published_at": null,
      "permalink": null,
      "metrics": null,
      "message_count": 2
    }
  ],
  "totals": {
    "impressions": 0,
    "reach": 0,
    "likes": 0,
    "comments": 0,
    "saves": 0,
    "shares": 0,
    "clicks": null,
    "video_views": 0
  }
}
GET/v1/campaigns/{id}

Get a campaign

A campaign with its creatives, placements (with latest metrics) and performance totals.

Scopecampaigns:readMCP toolget_campaign
Path parameters
idrequired
stringCampaign ID
Request
curl "https://croud.ai/api/v1/campaigns/cmp_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0cmp001",
  "object": "campaign",
  "name": "Autumn glow launch",
  "description": "Serum launch with mid-tier beauty creators",
  "type": "targeted",
  "objective": "launch",
  "category": "beauty",
  "status": "active",
  "offer_price_cents": null,
  "acceptance_mode": "instant",
  "collab": false,
  "collab_handles": [
    "lumen.skincare"
  ],
  "team_id": null,
  "persona_id": null,
  "budget_cents": 500000,
  "committed_cents": 0,
  "spent_cents": 0,
  "currency": "USD",
  "max_price_per_post_cents": 60000,
  "start_date": "2026-11-01T00:00:00.000Z",
  "end_date": "2026-11-30T00:00:00.000Z",
  "targeting": {
    "niches": [
      "beauty"
    ],
    "countries": [
      "US"
    ],
    "min_followers": 10000
  },
  "brand_safety": {},
  "landing_url": "https://lumen.example/serum",
  "utm": null,
  "brand_kit_id": "cmf0bk0001",
  "variants_enabled": true,
  "variant_config": {
    "angles": [
      "tutorial",
      "routine",
      "review"
    ],
    "design_template_ids": [
      "cmf0dt0001",
      "cmf0dt0002"
    ],
    "caption_template_ids": [],
    "brief": "Glow serum: 10% niacinamide, fragrance-free, $34. Launching November 1.",
    "must_include": {
      "hashtags": [
        "ad",
        "lumenglow"
      ],
      "mentions": [
        "lumen.skincare"
      ],
      "cta": "Shop the launch",
      "claims": [
        "Fragrance-free"
      ]
    },
    "avoid": [
      "cure",
      "miracle"
    ],
    "tailor_to_creator": true,
    "review": "review",
    "fallback_to_base": true,
    "slide_count": 5
  },
  "launched_at": null,
  "completed_at": null,
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z",
  "team": null,
  "persona": null,
  "creatives": [],
  "placements": [
    {
      "id": "cmf0plc001",
      "status": "scheduled",
      "origin": "matched",
      "is_collab": false,
      "price_cents": 45000,
      "account": {
        "id": "cmf0acc001",
        "username": "maya.creates",
        "followers": 48200
      },
      "creative": {
        "id": "cmf0crt001",
        "name": "Serum reel",
        "format": "ig_reel"
      },
      "scheduled_at": "2026-11-02T15:00:00.000Z",
      "published_at": null,
      "permalink": null,
      "metrics": null,
      "message_count": 2
    }
  ],
  "totals": {
    "impressions": 0,
    "reach": 0,
    "likes": 0,
    "comments": 0,
    "saves": 0,
    "shares": 0,
    "clicks": null,
    "video_views": 0
  }
}
PATCH/v1/campaigns/{id}

Update a campaign

Update any field of a draft or paused campaign. While a campaign is running only name, description, landing_url, budget_cents, end_date, persona_id, acceptance_mode, brand_kit_id and variant_config can change; the budget can't go below what's already committed. variant_config replaces the whole unique-posts configuration and applies to placements created afterwards.

Scopecampaigns:writeMCP toolupdate_campaign
Path parameters
idrequired
stringCampaign ID
Body
name
string
type
"targeted" | "open" | "direct"targeted (default): requests go to matching creators at their rates. open: you set offer_price_cents and creators accept from their account. direct: you send hand-picked creators requests (POST /v1/requests). Can only change while a draft.
objective
stringawareness | engagement | traffic | conversions | launch
category
stringAd category used for creator policy matching, e.g. beauty
description
string | null
landing_url
string | nullhttps:// URL
team_id
string | null
persona_id
string | nullBrand voice for AI-generated copy
budget_cents
integer
max_price_per_post_cents
integer | null
offer_price_cents
integer | nullOpen campaigns: price per post offered to every creator (at least the platform minimum)
acceptance_mode
"instant" | "review"Open campaigns: instant books the slot when a creator accepts; review creates an application you approve or decline
collab
booleanPosts are Instagram collab posts with your brand as collaborator (plan-gated)
collab_handles
string[]Instagram usernames invited as collaborators (max 3)
start_date
string | nullISO date or datetime; null = start at launch
end_date
string | nullISO date or datetime; null = run until budget is spent
targeting
objectWhich creator accounts the campaign matches
brand_kit_id
string | nullBrand kit for designs and unique-post visuals (defaults to the workspace's default kit)
variants_enabled
booleanWrite a unique post for every creator (plan feature creativeVariants; needs variant_config)
variant_config
object | null
Request
curl -X PATCH "https://croud.ai/api/v1/campaigns/cmp_123" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"budget_cents":750000,"end_date":"2026-12-15"}'
Response · 200
{
  "id": "cmf0cmp001",
  "object": "campaign",
  "name": "Autumn glow launch",
  "description": "Serum launch with mid-tier beauty creators",
  "type": "targeted",
  "objective": "launch",
  "category": "beauty",
  "status": "active",
  "offer_price_cents": null,
  "acceptance_mode": "instant",
  "collab": false,
  "collab_handles": [
    "lumen.skincare"
  ],
  "team_id": null,
  "persona_id": null,
  "budget_cents": 500000,
  "committed_cents": 0,
  "spent_cents": 0,
  "currency": "USD",
  "max_price_per_post_cents": 60000,
  "start_date": "2026-11-01T00:00:00.000Z",
  "end_date": "2026-11-30T00:00:00.000Z",
  "targeting": {
    "niches": [
      "beauty"
    ],
    "countries": [
      "US"
    ],
    "min_followers": 10000
  },
  "brand_safety": {},
  "landing_url": "https://lumen.example/serum",
  "utm": null,
  "brand_kit_id": "cmf0bk0001",
  "variants_enabled": true,
  "variant_config": {
    "angles": [
      "tutorial",
      "routine",
      "review"
    ],
    "design_template_ids": [
      "cmf0dt0001",
      "cmf0dt0002"
    ],
    "caption_template_ids": [],
    "brief": "Glow serum: 10% niacinamide, fragrance-free, $34. Launching November 1.",
    "must_include": {
      "hashtags": [
        "ad",
        "lumenglow"
      ],
      "mentions": [
        "lumen.skincare"
      ],
      "cta": "Shop the launch",
      "claims": [
        "Fragrance-free"
      ]
    },
    "avoid": [
      "cure",
      "miracle"
    ],
    "tailor_to_creator": true,
    "review": "review",
    "fallback_to_base": true,
    "slide_count": 5
  },
  "launched_at": null,
  "completed_at": null,
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z",
  "team": null,
  "persona": null,
  "creatives": [],
  "placements": [
    {
      "id": "cmf0plc001",
      "status": "scheduled",
      "origin": "matched",
      "is_collab": false,
      "price_cents": 45000,
      "account": {
        "id": "cmf0acc001",
        "username": "maya.creates",
        "followers": 48200
      },
      "creative": {
        "id": "cmf0crt001",
        "name": "Serum reel",
        "format": "ig_reel"
      },
      "scheduled_at": "2026-11-02T15:00:00.000Z",
      "published_at": null,
      "permalink": null,
      "metrics": null,
      "message_count": 2
    }
  ],
  "totals": {
    "impressions": 0,
    "reach": 0,
    "likes": 0,
    "comments": 0,
    "saves": 0,
    "shares": 0,
    "clicks": null,
    "video_views": 0
  }
}
DELETE/v1/campaigns/{id}

Delete a draft campaign

Deletes a draft that never launched. Its creatives stay in the library. Use archive for anything else.

Scopecampaigns:writeMCP tooldelete_campaign
Path parameters
idrequired
stringCampaign ID
Request
curl -X DELETE "https://croud.ai/api/v1/campaigns/cmp_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0cmp001",
  "object": "campaign",
  "deleted": true
}
POST/v1/campaigns/{id}/archive

Archive a campaign

Hides a draft, completed or canceled campaign from default lists.

Scopecampaigns:writeMCP toolarchive_campaign
Path parameters
idrequired
stringCampaign ID
Request
curl -X POST "https://croud.ai/api/v1/campaigns/cmp_123/archive" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0cmp001",
  "object": "campaign",
  "name": "Autumn glow launch",
  "description": "Serum launch with mid-tier beauty creators",
  "type": "targeted",
  "objective": "launch",
  "category": "beauty",
  "status": "archived",
  "offer_price_cents": null,
  "acceptance_mode": "instant",
  "collab": false,
  "collab_handles": [
    "lumen.skincare"
  ],
  "team_id": null,
  "persona_id": null,
  "budget_cents": 500000,
  "committed_cents": 0,
  "spent_cents": 0,
  "currency": "USD",
  "max_price_per_post_cents": 60000,
  "start_date": "2026-11-01T00:00:00.000Z",
  "end_date": "2026-11-30T00:00:00.000Z",
  "targeting": {
    "niches": [
      "beauty"
    ],
    "countries": [
      "US"
    ],
    "min_followers": 10000
  },
  "brand_safety": {},
  "landing_url": "https://lumen.example/serum",
  "utm": null,
  "brand_kit_id": "cmf0bk0001",
  "variants_enabled": true,
  "variant_config": {
    "angles": [
      "tutorial",
      "routine",
      "review"
    ],
    "design_template_ids": [
      "cmf0dt0001",
      "cmf0dt0002"
    ],
    "caption_template_ids": [],
    "brief": "Glow serum: 10% niacinamide, fragrance-free, $34. Launching November 1.",
    "must_include": {
      "hashtags": [
        "ad",
        "lumenglow"
      ],
      "mentions": [
        "lumen.skincare"
      ],
      "cta": "Shop the launch",
      "claims": [
        "Fragrance-free"
      ]
    },
    "avoid": [
      "cure",
      "miracle"
    ],
    "tailor_to_creator": true,
    "review": "review",
    "fallback_to_base": true,
    "slide_count": 5
  },
  "launched_at": null,
  "completed_at": null,
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z",
  "team": null,
  "persona": null,
  "creatives": [],
  "placements": [
    {
      "id": "cmf0plc001",
      "status": "scheduled",
      "origin": "matched",
      "is_collab": false,
      "price_cents": 45000,
      "account": {
        "id": "cmf0acc001",
        "username": "maya.creates",
        "followers": 48200
      },
      "creative": {
        "id": "cmf0crt001",
        "name": "Serum reel",
        "format": "ig_reel"
      },
      "scheduled_at": "2026-11-02T15:00:00.000Z",
      "published_at": null,
      "permalink": null,
      "metrics": null,
      "message_count": 2
    }
  ],
  "totals": {
    "impressions": 0,
    "reach": 0,
    "likes": 0,
    "comments": 0,
    "saves": 0,
    "shares": 0,
    "clicks": null,
    "video_views": 0
  }
}
POST/v1/campaigns/{id}/duplicate

Duplicate a campaign

Creates a new draft with the same settings, targeting and copies of its creatives.

Scopecampaigns:writeMCP toolduplicate_campaign
Path parameters
idrequired
stringCampaign ID
Request
curl -X POST "https://croud.ai/api/v1/campaigns/cmp_123/duplicate" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 201
{
  "id": "cmf0cmp001",
  "object": "campaign",
  "name": "Autumn glow launch",
  "description": "Serum launch with mid-tier beauty creators",
  "type": "targeted",
  "objective": "launch",
  "category": "beauty",
  "status": "active",
  "offer_price_cents": null,
  "acceptance_mode": "instant",
  "collab": false,
  "collab_handles": [
    "lumen.skincare"
  ],
  "team_id": null,
  "persona_id": null,
  "budget_cents": 500000,
  "committed_cents": 0,
  "spent_cents": 0,
  "currency": "USD",
  "max_price_per_post_cents": 60000,
  "start_date": "2026-11-01T00:00:00.000Z",
  "end_date": "2026-11-30T00:00:00.000Z",
  "targeting": {
    "niches": [
      "beauty"
    ],
    "countries": [
      "US"
    ],
    "min_followers": 10000
  },
  "brand_safety": {},
  "landing_url": "https://lumen.example/serum",
  "utm": null,
  "brand_kit_id": "cmf0bk0001",
  "variants_enabled": true,
  "variant_config": {
    "angles": [
      "tutorial",
      "routine",
      "review"
    ],
    "design_template_ids": [
      "cmf0dt0001",
      "cmf0dt0002"
    ],
    "caption_template_ids": [],
    "brief": "Glow serum: 10% niacinamide, fragrance-free, $34. Launching November 1.",
    "must_include": {
      "hashtags": [
        "ad",
        "lumenglow"
      ],
      "mentions": [
        "lumen.skincare"
      ],
      "cta": "Shop the launch",
      "claims": [
        "Fragrance-free"
      ]
    },
    "avoid": [
      "cure",
      "miracle"
    ],
    "tailor_to_creator": true,
    "review": "review",
    "fallback_to_base": true,
    "slide_count": 5
  },
  "launched_at": null,
  "completed_at": null,
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z",
  "team": null,
  "persona": null,
  "creatives": [],
  "placements": [
    {
      "id": "cmf0plc001",
      "status": "scheduled",
      "origin": "matched",
      "is_collab": false,
      "price_cents": 45000,
      "account": {
        "id": "cmf0acc001",
        "username": "maya.creates",
        "followers": 48200
      },
      "creative": {
        "id": "cmf0crt001",
        "name": "Serum reel",
        "format": "ig_reel"
      },
      "scheduled_at": "2026-11-02T15:00:00.000Z",
      "published_at": null,
      "permalink": null,
      "metrics": null,
      "message_count": 2
    }
  ],
  "totals": {
    "impressions": 0,
    "reach": 0,
    "likes": 0,
    "comments": 0,
    "saves": 0,
    "shares": 0,
    "clicks": null,
    "video_views": 0
  }
}
GET/v1/campaigns/{id}/readiness

Check launch readiness

Everything that would block or affect a launch: blocking error issues and advisory warnings, wallet coverage, eligible accounts and the estimated placements within budget.

Scopecampaigns:readMCP toolget_campaign_readiness
Path parameters
idrequired
stringCampaign ID
Request
curl "https://croud.ai/api/v1/campaigns/cmp_123/readiness" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "launch_readiness",
  "can_launch": false,
  "issues": [
    {
      "level": "error",
      "message": "Add at least one creative marked ready."
    }
  ],
  "ready_creatives": 0,
  "wallet": {
    "available_cents": 1250000,
    "reserved_cents": 90000
  },
  "preview": {
    "eligible_count": 12,
    "in_targeting": 18,
    "estimated": true
  },
  "estimate": {
    "count": 10,
    "cost_cents": 450000,
    "follower_reach": 480000
  }
}
POST/v1/campaigns/{id}/launch

Launch a campaign

Launches a draft campaign: checks formats, plan limits and wallet balance, then requests placements from every eligible creator account within budget. Creators with auto-approval accept instantly. Check /readiness first to see blocking issues.

Scopecampaigns:writeMCP toollaunch_campaign
Path parameters
idrequired
stringCampaign ID
Request
curl -X POST "https://croud.ai/api/v1/campaigns/cmp_123/launch" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "campaign_launch",
  "campaign": {
    "id": "cmf0cmp001",
    "object": "campaign",
    "name": "Autumn glow launch",
    "description": "Serum launch with mid-tier beauty creators",
    "type": "targeted",
    "objective": "launch",
    "category": "beauty",
    "status": "active",
    "offer_price_cents": null,
    "acceptance_mode": "instant",
    "collab": false,
    "collab_handles": [
      "lumen.skincare"
    ],
    "team_id": null,
    "persona_id": null,
    "budget_cents": 500000,
    "committed_cents": 0,
    "spent_cents": 0,
    "currency": "USD",
    "max_price_per_post_cents": 60000,
    "start_date": "2026-11-01T00:00:00.000Z",
    "end_date": "2026-11-30T00:00:00.000Z",
    "targeting": {
      "niches": [
        "beauty"
      ],
      "countries": [
        "US"
      ],
      "min_followers": 10000
    },
    "brand_safety": {},
    "landing_url": "https://lumen.example/serum",
    "utm": null,
    "brand_kit_id": "cmf0bk0001",
    "variants_enabled": true,
    "variant_config": {
      "angles": [
        "tutorial",
        "routine",
        "review"
      ],
      "design_template_ids": [
        "cmf0dt0001",
        "cmf0dt0002"
      ],
      "caption_template_ids": [],
      "brief": "Glow serum: 10% niacinamide, fragrance-free, $34. Launching November 1.",
      "must_include": {
        "hashtags": [
          "ad",
          "lumenglow"
        ],
        "mentions": [
          "lumen.skincare"
        ],
        "cta": "Shop the launch",
        "claims": [
          "Fragrance-free"
        ]
      },
      "avoid": [
        "cure",
        "miracle"
      ],
      "tailor_to_creator": true,
      "review": "review",
      "fallback_to_base": true,
      "slide_count": 5
    },
    "launched_at": null,
    "completed_at": null,
    "created_at": "2026-10-20T10:00:00.000Z",
    "updated_at": "2026-10-28T10:00:00.000Z"
  },
  "placements_requested": 6
}
POST/v1/campaigns/{id}/pause

Pause a campaign

Stops requesting new placements for an active or scheduled campaign. Already scheduled placements still publish; cancel them individually if needed.

Scopecampaigns:writeMCP toolpause_campaign
Path parameters
idrequired
stringCampaign ID
Request
curl -X POST "https://croud.ai/api/v1/campaigns/cmp_123/pause" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0cmp001",
  "object": "campaign",
  "name": "Autumn glow launch",
  "description": "Serum launch with mid-tier beauty creators",
  "type": "targeted",
  "objective": "launch",
  "category": "beauty",
  "status": "paused",
  "offer_price_cents": null,
  "acceptance_mode": "instant",
  "collab": false,
  "collab_handles": [
    "lumen.skincare"
  ],
  "team_id": null,
  "persona_id": null,
  "budget_cents": 500000,
  "committed_cents": 0,
  "spent_cents": 0,
  "currency": "USD",
  "max_price_per_post_cents": 60000,
  "start_date": "2026-11-01T00:00:00.000Z",
  "end_date": "2026-11-30T00:00:00.000Z",
  "targeting": {
    "niches": [
      "beauty"
    ],
    "countries": [
      "US"
    ],
    "min_followers": 10000
  },
  "brand_safety": {},
  "landing_url": "https://lumen.example/serum",
  "utm": null,
  "brand_kit_id": "cmf0bk0001",
  "variants_enabled": true,
  "variant_config": {
    "angles": [
      "tutorial",
      "routine",
      "review"
    ],
    "design_template_ids": [
      "cmf0dt0001",
      "cmf0dt0002"
    ],
    "caption_template_ids": [],
    "brief": "Glow serum: 10% niacinamide, fragrance-free, $34. Launching November 1.",
    "must_include": {
      "hashtags": [
        "ad",
        "lumenglow"
      ],
      "mentions": [
        "lumen.skincare"
      ],
      "cta": "Shop the launch",
      "claims": [
        "Fragrance-free"
      ]
    },
    "avoid": [
      "cure",
      "miracle"
    ],
    "tailor_to_creator": true,
    "review": "review",
    "fallback_to_base": true,
    "slide_count": 5
  },
  "launched_at": null,
  "completed_at": null,
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z",
  "team": null,
  "persona": null,
  "creatives": [],
  "placements": [
    {
      "id": "cmf0plc001",
      "status": "scheduled",
      "origin": "matched",
      "is_collab": false,
      "price_cents": 45000,
      "account": {
        "id": "cmf0acc001",
        "username": "maya.creates",
        "followers": 48200
      },
      "creative": {
        "id": "cmf0crt001",
        "name": "Serum reel",
        "format": "ig_reel"
      },
      "scheduled_at": "2026-11-02T15:00:00.000Z",
      "published_at": null,
      "permalink": null,
      "metrics": null,
      "message_count": 2
    }
  ],
  "totals": {
    "impressions": 0,
    "reach": 0,
    "likes": 0,
    "comments": 0,
    "saves": 0,
    "shares": 0,
    "clicks": null,
    "video_views": 0
  }
}
POST/v1/campaigns/{id}/resume

Resume a campaign

Resumes a paused campaign: re-checks the wallet and requests any newly eligible accounts.

Scopecampaigns:writeMCP toolresume_campaign
Path parameters
idrequired
stringCampaign ID
Request
curl -X POST "https://croud.ai/api/v1/campaigns/cmp_123/resume" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "campaign_launch",
  "campaign": {
    "id": "cmf0cmp001",
    "object": "campaign",
    "name": "Autumn glow launch",
    "description": "Serum launch with mid-tier beauty creators",
    "type": "targeted",
    "objective": "launch",
    "category": "beauty",
    "status": "active",
    "offer_price_cents": null,
    "acceptance_mode": "instant",
    "collab": false,
    "collab_handles": [
      "lumen.skincare"
    ],
    "team_id": null,
    "persona_id": null,
    "budget_cents": 500000,
    "committed_cents": 0,
    "spent_cents": 0,
    "currency": "USD",
    "max_price_per_post_cents": 60000,
    "start_date": "2026-11-01T00:00:00.000Z",
    "end_date": "2026-11-30T00:00:00.000Z",
    "targeting": {
      "niches": [
        "beauty"
      ],
      "countries": [
        "US"
      ],
      "min_followers": 10000
    },
    "brand_safety": {},
    "landing_url": "https://lumen.example/serum",
    "utm": null,
    "brand_kit_id": "cmf0bk0001",
    "variants_enabled": true,
    "variant_config": {
      "angles": [
        "tutorial",
        "routine",
        "review"
      ],
      "design_template_ids": [
        "cmf0dt0001",
        "cmf0dt0002"
      ],
      "caption_template_ids": [],
      "brief": "Glow serum: 10% niacinamide, fragrance-free, $34. Launching November 1.",
      "must_include": {
        "hashtags": [
          "ad",
          "lumenglow"
        ],
        "mentions": [
          "lumen.skincare"
        ],
        "cta": "Shop the launch",
        "claims": [
          "Fragrance-free"
        ]
      },
      "avoid": [
        "cure",
        "miracle"
      ],
      "tailor_to_creator": true,
      "review": "review",
      "fallback_to_base": true,
      "slide_count": 5
    },
    "launched_at": null,
    "completed_at": null,
    "created_at": "2026-10-20T10:00:00.000Z",
    "updated_at": "2026-10-28T10:00:00.000Z"
  },
  "placements_requested": 1
}
POST/v1/campaigns/{id}/cancel

Cancel a campaign

Cancels the campaign and every unpublished placement, releasing reserved funds. Published placements are unaffected. This can't be undone.

Scopecampaigns:writeMCP toolcancel_campaign
Path parameters
idrequired
stringCampaign ID
Request
curl -X POST "https://croud.ai/api/v1/campaigns/cmp_123/cancel" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0cmp001",
  "object": "campaign",
  "name": "Autumn glow launch",
  "description": "Serum launch with mid-tier beauty creators",
  "type": "targeted",
  "objective": "launch",
  "category": "beauty",
  "status": "canceled",
  "offer_price_cents": null,
  "acceptance_mode": "instant",
  "collab": false,
  "collab_handles": [
    "lumen.skincare"
  ],
  "team_id": null,
  "persona_id": null,
  "budget_cents": 500000,
  "committed_cents": 0,
  "spent_cents": 0,
  "currency": "USD",
  "max_price_per_post_cents": 60000,
  "start_date": "2026-11-01T00:00:00.000Z",
  "end_date": "2026-11-30T00:00:00.000Z",
  "targeting": {
    "niches": [
      "beauty"
    ],
    "countries": [
      "US"
    ],
    "min_followers": 10000
  },
  "brand_safety": {},
  "landing_url": "https://lumen.example/serum",
  "utm": null,
  "brand_kit_id": "cmf0bk0001",
  "variants_enabled": true,
  "variant_config": {
    "angles": [
      "tutorial",
      "routine",
      "review"
    ],
    "design_template_ids": [
      "cmf0dt0001",
      "cmf0dt0002"
    ],
    "caption_template_ids": [],
    "brief": "Glow serum: 10% niacinamide, fragrance-free, $34. Launching November 1.",
    "must_include": {
      "hashtags": [
        "ad",
        "lumenglow"
      ],
      "mentions": [
        "lumen.skincare"
      ],
      "cta": "Shop the launch",
      "claims": [
        "Fragrance-free"
      ]
    },
    "avoid": [
      "cure",
      "miracle"
    ],
    "tailor_to_creator": true,
    "review": "review",
    "fallback_to_base": true,
    "slide_count": 5
  },
  "launched_at": null,
  "completed_at": null,
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z",
  "team": null,
  "persona": null,
  "creatives": [],
  "placements": [
    {
      "id": "cmf0plc001",
      "status": "scheduled",
      "origin": "matched",
      "is_collab": false,
      "price_cents": 45000,
      "account": {
        "id": "cmf0acc001",
        "username": "maya.creates",
        "followers": 48200
      },
      "creative": {
        "id": "cmf0crt001",
        "name": "Serum reel",
        "format": "ig_reel"
      },
      "scheduled_at": "2026-11-02T15:00:00.000Z",
      "published_at": null,
      "permalink": null,
      "metrics": null,
      "message_count": 2
    }
  ],
  "totals": {
    "impressions": 0,
    "reach": 0,
    "likes": 0,
    "comments": 0,
    "saves": 0,
    "shares": 0,
    "clicks": null,
    "video_views": 0
  }
}
GET/v1/campaigns/{id}/matches

Preview campaign matches

Dry-run matching against every listed creator account: whether it's in targeting, eligible under the creator's policy for this campaign's ready creatives, the price, and the reasons when it isn't. Without ready creatives the result is an estimate (estimated: true). Nothing is requested.

Scopecampaigns:readMCP toolpreview_campaign_matches
Path parameters
idrequired
stringCampaign ID
Query parameters
eligible_only
boolean | "0" | "1" | "true" | "false"Only return eligible accounts
limit
integerMax accounts to return (default 50)
Request
curl "https://croud.ai/api/v1/campaigns/cmp_123/matches" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "match_preview",
  "campaign_id": "cmf0cmp001",
  "estimated": false,
  "total_listed": 40,
  "in_targeting": 18,
  "eligible_count": 12,
  "eligible_reach": 640000,
  "data": [
    {
      "id": "cmf0acc001",
      "username": "maya.creates",
      "display_name": "Maya",
      "avatar_url": null,
      "followers": 48200,
      "engagement_rate": 4.1,
      "country": "US",
      "niches": [
        "beauty"
      ],
      "in_targeting": true,
      "eligible": true,
      "price_cents": 45000,
      "format_key": "ig_reel",
      "creative_name": "Serum reel",
      "reasons": []
    }
  ]
}
Reference

Creatives

Ad creatives (caption, hashtags, media) attached to campaigns, and the media library.

GET/v1/media

List media

Images and videos in the workspace's media library, newest first. Use an item's id as media[].asset_id and its url in a creative.

Scopecreatives:readMCP toollist_media
Query parameters
limit
integerPage size, 1–100 (default 25)
cursor
stringnext_cursor from the previous page
type
"image" | "video"
folder
stringFolder name
search
stringMatch on the file name
Request
curl "https://croud.ai/api/v1/media" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0med001",
      "object": "media",
      "url": "https://croud.ai/uploads/ws/serum.jpg",
      "filename": "serum.jpg",
      "type": "image",
      "mime_type": "image/jpeg",
      "size_bytes": 248120,
      "width": 1080,
      "height": 1350,
      "duration_sec": null,
      "folder": "Autumn launch",
      "created_at": "2026-10-20T10:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
POST/v1/media

Add media from a URL

Downloads a public https:// image or video into the media library. Files are checked by content (JPEG, PNG, WebP, GIF, MP4, MOV, WebM) and size, and count toward the plan's storage. For videos, pass width, height and duration_sec.

Scopecreatives:writeMCP tooladd_media_from_url
Body
urlrequired
stringPublic https:// URL of the file
filename
string
folder
string | null
width
integer
height
integer
duration_sec
number
Request
curl -X POST "https://croud.ai/api/v1/media" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://cdn.lumen.example/serum.jpg","folder":"Autumn launch"}'
Response · 201
{
  "id": "cmf0med001",
  "object": "media",
  "url": "https://croud.ai/uploads/ws/serum.jpg",
  "filename": "serum.jpg",
  "type": "image",
  "mime_type": "image/jpeg",
  "size_bytes": 248120,
  "width": 1080,
  "height": 1350,
  "duration_sec": null,
  "folder": "Autumn launch",
  "created_at": "2026-10-20T10:00:00.000Z"
}
DELETE/v1/media/{id}

Delete media

Deletes a file from the library. Refused while a ready creative, a design, a brand kit or a booked post uses it.

Scopecreatives:writeMCP tooldelete_media
Path parameters
idrequired
stringMedia ID
Request
curl -X DELETE "https://croud.ai/api/v1/media/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0med001",
  "object": "media",
  "deleted": true
}
GET/v1/creatives

List creatives

Creatives in the library, most recently updated first. Archived creatives are excluded unless status=archived or status=all. Unique posts written per creator (kind: variant) are only listed with kind=variant or kind=all.

Scopecreatives:readMCP toollist_creatives
Query parameters
limit
integerPage size, 1–100 (default 25)
cursor
stringnext_cursor from the previous page
status
"draft" | "ready" | "archived" | "all"
format
stringFormat key
campaign_id
string
search
stringMatch on name or caption
kind
"standard" | "variant" | "all"standard (default) = your library; variant = unique posts written per creator; all
Request
curl "https://croud.ai/api/v1/creatives" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0crt001",
      "object": "creative",
      "name": "Serum reel",
      "campaign_id": "cmf0cmp001",
      "template_id": null,
      "persona_id": null,
      "format": "ig_reel",
      "caption": "Glow season is here. #ad",
      "hashtags": [
        "ad",
        "skincare"
      ],
      "cta": "Shop now",
      "link_url": "https://lumen.example/serum",
      "media": [
        {
          "url": "https://cdn.example/serum.mp4",
          "type": "video",
          "width": 1080,
          "height": 1920,
          "duration_sec": 21
        }
      ],
      "status": "ready",
      "ai_generated": false,
      "version": 2,
      "kind": "standard",
      "parent_id": null,
      "variant_for_account_id": null,
      "angle": null,
      "design_template_id": null,
      "caption_template_id": null,
      "variant_status": null,
      "design_id": null,
      "created_at": "2026-10-20T10:00:00.000Z",
      "updated_at": "2026-10-21T09:00:00.000Z",
      "campaign": {
        "id": "cmf0cmp001",
        "name": "Autumn glow launch",
        "status": "draft"
      },
      "persona": null,
      "placement_count": 0
    }
  ],
  "has_more": false,
  "next_cursor": null
}
POST/v1/creatives

Create a creative

Creates a creative in the library, optionally attached to a campaign. Drafts can use draft_only formats; ready creatives must pass the format's caption, hashtag and media specs and can be sent to creators.

Scopecreatives:writeMCP toolcreate_creative
Body
namerequired
string
formatrequired
stringFormat key, e.g. ig_reel (see GET /v1/formats)
caption
string
hashtags
string[]With or without the leading #
cta
string | nullCall to action, e.g. Shop now
link_url
string | null
media
object[]
persona_id
string | null
template_id
string | null
campaign_id
string | nullAttach to a campaign
ai_generated
booleanDisclose AI-generated content (some creators decline it). Creatives saved from an AI-assisted design and per-creator variants are always marked
status
"draft" | "ready"ready validates against the format specs
Request
curl -X POST "https://croud.ai/api/v1/creatives" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Serum reel","format":"ig_reel","caption":"Glow season is here. #ad","hashtags":["skincare"],"cta":"Shop now","link_url":"https://lumen.example/serum","media":[{"url":"https://cdn.example/serum.mp4","type":"video","width":1080,"height":1920,"duration_sec":21}],"campaign_id":"cmf0cmp001","status":"ready"}'
Response · 201
{
  "id": "cmf0crt001",
  "object": "creative",
  "name": "Serum reel",
  "campaign_id": "cmf0cmp001",
  "template_id": null,
  "persona_id": null,
  "format": "ig_reel",
  "caption": "Glow season is here. #ad",
  "hashtags": [
    "ad",
    "skincare"
  ],
  "cta": "Shop now",
  "link_url": "https://lumen.example/serum",
  "media": [
    {
      "url": "https://cdn.example/serum.mp4",
      "type": "video",
      "width": 1080,
      "height": 1920,
      "duration_sec": 21
    }
  ],
  "status": "ready",
  "ai_generated": false,
  "version": 2,
  "kind": "standard",
  "parent_id": null,
  "variant_for_account_id": null,
  "angle": null,
  "design_template_id": null,
  "caption_template_id": null,
  "variant_status": null,
  "design_id": null,
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-21T09:00:00.000Z",
  "campaign": {
    "id": "cmf0cmp001",
    "name": "Autumn glow launch",
    "status": "draft"
  },
  "persona": null,
  "placement_count": 0
}
GET/v1/creatives/{id}

Get a creative

Retrieve one creative.

Scopecreatives:readMCP toolget_creative
Path parameters
idrequired
stringCreative ID
Request
curl "https://croud.ai/api/v1/creatives/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0crt001",
  "object": "creative",
  "name": "Serum reel",
  "campaign_id": "cmf0cmp001",
  "template_id": null,
  "persona_id": null,
  "format": "ig_reel",
  "caption": "Glow season is here. #ad",
  "hashtags": [
    "ad",
    "skincare"
  ],
  "cta": "Shop now",
  "link_url": "https://lumen.example/serum",
  "media": [
    {
      "url": "https://cdn.example/serum.mp4",
      "type": "video",
      "width": 1080,
      "height": 1920,
      "duration_sec": 21
    }
  ],
  "status": "ready",
  "ai_generated": false,
  "version": 2,
  "kind": "standard",
  "parent_id": null,
  "variant_for_account_id": null,
  "angle": null,
  "design_template_id": null,
  "caption_template_id": null,
  "variant_status": null,
  "design_id": null,
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-21T09:00:00.000Z",
  "campaign": {
    "id": "cmf0cmp001",
    "name": "Autumn glow launch",
    "status": "draft"
  },
  "persona": null,
  "placement_count": 0
}
PATCH/v1/creatives/{id}

Update a creative

Update fields; omitted fields keep their values. Content changes bump version. The format can't change once a placement is scheduled or published. Set status to archived to archive, or back to draft to restore.

Scopecreatives:writeMCP toolupdate_creative
Path parameters
idrequired
stringCreative ID
Body
name
string
format
stringFormat key, e.g. ig_reel (see GET /v1/formats)
caption
string
hashtags
string[]With or without the leading #
cta
string | nullCall to action, e.g. Shop now
link_url
string | null
media
object[]
persona_id
string | null
template_id
string | null
campaign_id
string | nullAttach to a campaign
ai_generated
booleanDisclose AI-generated content (some creators decline it). Creatives saved from an AI-assisted design and per-creator variants are always marked
status
"draft" | "ready" | "archived"ready validates against the format specs; archived hides it
Request
curl -X PATCH "https://croud.ai/api/v1/creatives/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"caption":"#ad Glow season is here.","status":"ready"}'
Response · 200
{
  "id": "cmf0crt001",
  "object": "creative",
  "name": "Serum reel",
  "campaign_id": "cmf0cmp001",
  "template_id": null,
  "persona_id": null,
  "format": "ig_reel",
  "caption": "Glow season is here. #ad",
  "hashtags": [
    "ad",
    "skincare"
  ],
  "cta": "Shop now",
  "link_url": "https://lumen.example/serum",
  "media": [
    {
      "url": "https://cdn.example/serum.mp4",
      "type": "video",
      "width": 1080,
      "height": 1920,
      "duration_sec": 21
    }
  ],
  "status": "ready",
  "ai_generated": false,
  "version": 3,
  "kind": "standard",
  "parent_id": null,
  "variant_for_account_id": null,
  "angle": null,
  "design_template_id": null,
  "caption_template_id": null,
  "variant_status": null,
  "design_id": null,
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-21T09:00:00.000Z",
  "campaign": {
    "id": "cmf0cmp001",
    "name": "Autumn glow launch",
    "status": "draft"
  },
  "persona": null,
  "placement_count": 0
}
DELETE/v1/creatives/{id}

Delete a creative

Permanently deletes a creative that has never been used in a placement. Archive it otherwise.

Scopecreatives:writeMCP tooldelete_creative
Path parameters
idrequired
stringCreative ID
Request
curl -X DELETE "https://croud.ai/api/v1/creatives/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0crt001",
  "object": "creative",
  "deleted": true
}
POST/v1/creatives/{id}/duplicate

Duplicate a creative

Copies a creative as a new draft, optionally into another campaign.

Scopecreatives:writeMCP toolduplicate_creative
Path parameters
idrequired
stringCreative ID
Body
campaign_id
string | nullCampaign for the copy (defaults to the original's)
Request
curl -X POST "https://croud.ai/api/v1/creatives/id_123/duplicate" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
Response · 201
{
  "id": "cmf0crt002",
  "object": "creative",
  "name": "Serum reel (copy)",
  "campaign_id": "cmf0cmp001",
  "template_id": null,
  "persona_id": null,
  "format": "ig_reel",
  "caption": "Glow season is here. #ad",
  "hashtags": [
    "ad",
    "skincare"
  ],
  "cta": "Shop now",
  "link_url": "https://lumen.example/serum",
  "media": [
    {
      "url": "https://cdn.example/serum.mp4",
      "type": "video",
      "width": 1080,
      "height": 1920,
      "duration_sec": 21
    }
  ],
  "status": "draft",
  "ai_generated": false,
  "version": 1,
  "kind": "standard",
  "parent_id": null,
  "variant_for_account_id": null,
  "angle": null,
  "design_template_id": null,
  "caption_template_id": null,
  "variant_status": null,
  "design_id": null,
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-21T09:00:00.000Z",
  "campaign": {
    "id": "cmf0cmp001",
    "name": "Autumn glow launch",
    "status": "draft"
  },
  "persona": null,
  "placement_count": 0
}
POST/v1/campaigns/{id}/creatives

Add a creative to a campaign

Attaches a library creative to a campaign. An unassigned creative moves into the campaign; one that already belongs to another campaign is copied, so that campaign keeps its content (the copy stays ready if the original was and still validates). Returns the creative now in the campaign.

Scopecreatives:writeMCP toolattach_creative_to_campaign
Path parameters
idrequired
stringCampaign ID
Body
creative_idrequired
stringCreative to add
Request
curl -X POST "https://croud.ai/api/v1/campaigns/id_123/creatives" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"creative_id":"cmf0crt001"}'
Response · 201
{
  "id": "cmf0crt001",
  "object": "creative",
  "name": "Serum reel",
  "campaign_id": "cmf0cmp001",
  "template_id": null,
  "persona_id": null,
  "format": "ig_reel",
  "caption": "Glow season is here. #ad",
  "hashtags": [
    "ad",
    "skincare"
  ],
  "cta": "Shop now",
  "link_url": "https://lumen.example/serum",
  "media": [
    {
      "url": "https://cdn.example/serum.mp4",
      "type": "video",
      "width": 1080,
      "height": 1920,
      "duration_sec": 21
    }
  ],
  "status": "ready",
  "ai_generated": false,
  "version": 2,
  "kind": "standard",
  "parent_id": null,
  "variant_for_account_id": null,
  "angle": null,
  "design_template_id": null,
  "caption_template_id": null,
  "variant_status": null,
  "design_id": null,
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-21T09:00:00.000Z",
  "campaign": {
    "id": "cmf0cmp001",
    "name": "Autumn glow launch",
    "status": "draft"
  },
  "persona": null,
  "placement_count": 0
}
DELETE/v1/campaigns/{id}/creatives/{creative_id}

Remove a creative from a campaign

Moves a creative out of the campaign back to the library (it isn't deleted). Refused while the creative has open placements in the campaign.

Scopecreatives:writeMCP tooldetach_creative_from_campaign
Path parameters
idrequired
stringCampaign ID
creative_idrequired
stringCreative ID
Request
curl -X DELETE "https://croud.ai/api/v1/campaigns/id_123/creatives/creative_id" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0crt001",
  "object": "creative",
  "name": "Serum reel",
  "campaign_id": null,
  "template_id": null,
  "persona_id": null,
  "format": "ig_reel",
  "caption": "Glow season is here. #ad",
  "hashtags": [
    "ad",
    "skincare"
  ],
  "cta": "Shop now",
  "link_url": "https://lumen.example/serum",
  "media": [
    {
      "url": "https://cdn.example/serum.mp4",
      "type": "video",
      "width": 1080,
      "height": 1920,
      "duration_sec": 21
    }
  ],
  "status": "ready",
  "ai_generated": false,
  "version": 2,
  "kind": "standard",
  "parent_id": null,
  "variant_for_account_id": null,
  "angle": null,
  "design_template_id": null,
  "caption_template_id": null,
  "variant_status": null,
  "design_id": null,
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-21T09:00:00.000Z",
  "campaign": null,
  "persona": null,
  "placement_count": 0
}
POST/v1/creatives/render-template

Render a template

Fills a template's variables and returns the caption, hashtags and CTA to use in a creative. Nothing is saved.

Scopecreatives:writeMCP toolrender_template
Body
template_idrequired
string
values
objectTemplate variable values, e.g. { "product": "Glow serum" }
Request
curl -X POST "https://croud.ai/api/v1/creatives/render-template" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"template_id":"cmf0tpl001","values":{"product":"Glow serum","discount":"20%"}}'
Response · 200
{
  "object": "rendered_template",
  "template_id": "cmf0tpl001",
  "format_key": "ig_carousel",
  "caption": "Meet Glow serum — 20% off this week.",
  "hashtags": [
    "skincare"
  ],
  "cta": "Shop now",
  "media_guidance": "5 square slides, product first"
}
Reference

Unique posts

Per-creator variants: with unique posts on, every creator gets a post with its own angle, caption and design. Review, edit, rewrite or approve them.

GET/v1/campaigns/{id}/variants

List a campaign's unique posts

Every variant written for the campaign's creators with its placement, angle, design and uniqueness score, plus counts by variant_status and the placements whose post is still being written (writing).

Scopecampaigns:readMCP toollist_campaign_variants
Path parameters
idrequired
stringCampaign ID
Request
curl "https://croud.ai/api/v1/campaigns/id_123/variants" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "variant_list",
  "campaign_id": "cmf0cmp001",
  "enabled": true,
  "config": {
    "angles": [
      "tutorial",
      "routine"
    ],
    "design_template_ids": [
      "cmf0dt0002"
    ],
    "caption_template_ids": [],
    "brief": "Glow serum: 10% niacinamide, fragrance-free, $34.",
    "must_include": {
      "hashtags": [
        "ad"
      ],
      "mentions": [],
      "cta": null,
      "claims": []
    },
    "avoid": [],
    "tailor_to_creator": true,
    "review": "review",
    "fallback_to_base": true,
    "slide_count": 5
  },
  "counts": {
    "awaiting_review": 1,
    "approved": 4,
    "writing": 2
  },
  "writing": [
    {
      "placement_id": "cmf0plc007",
      "account": {
        "id": "cmf0acc007",
        "username": "techbyleo",
        "avatar_url": null
      }
    }
  ],
  "data": [
    {
      "id": "cmf0crt101",
      "object": "variant",
      "name": "Serum carousel — @maya.creates",
      "campaign_id": "cmf0cmp001",
      "template_id": null,
      "persona_id": null,
      "format": "ig_carousel",
      "caption": "I swapped my evening serum for two weeks. Here's what changed (and what didn't). Fragrance-free, which my skin needed. #ad #lumenglow @lumen.skincare",
      "hashtags": [
        "ad",
        "lumenglow",
        "skincareroutine"
      ],
      "cta": "Shop the launch",
      "link_url": "https://lumen.example/serum",
      "media": [
        {
          "asset_id": "cmf0med101",
          "url": "https://croud.ai/uploads/ws/slide-1.png",
          "type": "image",
          "width": 1080,
          "height": 1350
        }
      ],
      "status": "ready",
      "ai_generated": true,
      "version": 1,
      "kind": "variant",
      "parent_id": "cmf0crt001",
      "variant_for_account_id": "cmf0acc001",
      "angle": "routine",
      "design_template_id": "cmf0dt0002",
      "caption_template_id": null,
      "variant_status": "awaiting_review",
      "design_id": "cmf0dsn101",
      "created_at": "2026-11-01T09:00:00.000Z",
      "updated_at": "2026-11-01T09:00:00.000Z",
      "placement": {
        "id": "cmf0plc001",
        "status": "drafting",
        "origin": "matched",
        "price_cents": 45000,
        "account": {
          "id": "cmf0acc001",
          "username": "maya.creates",
          "avatar_url": null,
          "followers": 48200
        }
      },
      "design": {
        "id": "cmf0dsn101",
        "name": "Autumn glow launch · @maya.creates",
        "thumbnail_url": null
      },
      "generation": {
        "similarity": 0.12,
        "threshold": 0.35,
        "attempts": 1,
        "credits": 12,
        "model": "claude-opus-5-5",
        "hook": "I swapped my evening serum for two weeks",
        "error": null
      }
    }
  ]
}
POST/v1/campaigns/{id}/variants/approve

Approve all waiting posts

Approves every variant of the campaign that is awaiting_review; each placement continues to the creator (or is scheduled for accepted open-campaign slots).

Scopecampaigns:writeMCP toolapprove_all_variants
Path parameters
idrequired
stringCampaign ID
Request
curl -X POST "https://croud.ai/api/v1/campaigns/id_123/variants/approve" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "variant_approval",
  "campaign_id": "cmf0cmp001",
  "approved": 6
}
POST/v1/variants/{id}/approve

Approve a unique post

Approves a variant that is awaiting_review (or a hand-fixed failed one). Its placement continues to the creator's review, or is scheduled for an accepted open-campaign slot.

Scopecampaigns:writeMCP toolapprove_variant
Path parameters
idrequired
stringVariant (creative) ID
Request
curl -X POST "https://croud.ai/api/v1/variants/id_123/approve" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0crt101",
  "object": "variant",
  "name": "Serum carousel — @maya.creates",
  "campaign_id": "cmf0cmp001",
  "template_id": null,
  "persona_id": null,
  "format": "ig_carousel",
  "caption": "I swapped my evening serum for two weeks. Here's what changed (and what didn't). Fragrance-free, which my skin needed. #ad #lumenglow @lumen.skincare",
  "hashtags": [
    "ad",
    "lumenglow",
    "skincareroutine"
  ],
  "cta": "Shop the launch",
  "link_url": "https://lumen.example/serum",
  "media": [
    {
      "asset_id": "cmf0med101",
      "url": "https://croud.ai/uploads/ws/slide-1.png",
      "type": "image",
      "width": 1080,
      "height": 1350
    }
  ],
  "status": "ready",
  "ai_generated": true,
  "version": 1,
  "kind": "variant",
  "parent_id": "cmf0crt001",
  "variant_for_account_id": "cmf0acc001",
  "angle": "routine",
  "design_template_id": "cmf0dt0002",
  "caption_template_id": null,
  "variant_status": "approved",
  "design_id": "cmf0dsn101",
  "created_at": "2026-11-01T09:00:00.000Z",
  "updated_at": "2026-11-01T09:00:00.000Z"
}
PATCH/v1/variants/{id}

Edit a unique post

Hand-edit a variant's caption, hashtags and CTA while it's awaiting review, failed, or when the creator requested changes. The caption must still pass the format's specs; the uniqueness score is recomputed. A failed variant moves back to awaiting_review.

Scopecampaigns:writeMCP toolupdate_variant
Path parameters
idrequired
stringVariant (creative) ID
Body
captionrequired
string
hashtagsrequired
string[]With or without the leading #
cta
string | null
Request
curl -X PATCH "https://croud.ai/api/v1/variants/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"caption":"Two weeks with the Glow serum: my honest notes. #ad @lumen.skincare","hashtags":["ad","lumenglow"],"cta":"Shop the launch"}'
Response · 200
{
  "id": "cmf0crt101",
  "object": "variant",
  "name": "Serum carousel — @maya.creates",
  "campaign_id": "cmf0cmp001",
  "template_id": null,
  "persona_id": null,
  "format": "ig_carousel",
  "caption": "I swapped my evening serum for two weeks. Here's what changed (and what didn't). Fragrance-free, which my skin needed. #ad #lumenglow @lumen.skincare",
  "hashtags": [
    "ad",
    "lumenglow",
    "skincareroutine"
  ],
  "cta": "Shop the launch",
  "link_url": "https://lumen.example/serum",
  "media": [
    {
      "asset_id": "cmf0med101",
      "url": "https://croud.ai/uploads/ws/slide-1.png",
      "type": "image",
      "width": 1080,
      "height": 1350
    }
  ],
  "status": "ready",
  "ai_generated": true,
  "version": 2,
  "kind": "variant",
  "parent_id": "cmf0crt001",
  "variant_for_account_id": "cmf0acc001",
  "angle": "routine",
  "design_template_id": "cmf0dt0002",
  "caption_template_id": null,
  "variant_status": "awaiting_review",
  "design_id": "cmf0dsn101",
  "created_at": "2026-11-01T09:00:00.000Z",
  "updated_at": "2026-11-01T09:00:00.000Z"
}
POST/v1/variants/{id}/regenerate

Rewrite a unique post

Queues a rewrite, optionally with another angle, design template or revision notes (the creator's change request is used when you send none). The current version is replaced when the new one is ready (creative.variant_ready); if the rewrite fails the current version is kept. Up to 5 rewrites per post per hour. Uses AI credits.

Scopecampaigns:writeMCP toolregenerate_variant
Path parameters
idrequired
stringVariant (creative) ID
Body
angle
string | nullcreative_angle key
design_template_id
string | nullDesign template for the visuals; null = keep the base creative's media
instructions
string | nullRevision notes for the AI
Request
curl -X POST "https://croud.ai/api/v1/variants/id_123/regenerate" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"angle":"review","instructions":"Shorter, and mention it's fragrance-free."}'
Response · 202
{
  "object": "variant_regeneration",
  "id": "cmf0crt101",
  "variant_status": "generating",
  "queued": true
}
POST/v1/variants/{id}/use-base

Send the base creative instead

Skips a variant that's waiting for review: the placement gets the campaign's base creative and continues to the creator. The variant is archived (variant_status: replaced).

Scopecampaigns:writeMCP tooluse_base_creative
Path parameters
idrequired
stringVariant (creative) ID
Request
curl -X POST "https://croud.ai/api/v1/variants/id_123/use-base" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0crt101",
  "object": "variant",
  "name": "Serum carousel — @maya.creates",
  "campaign_id": "cmf0cmp001",
  "template_id": null,
  "persona_id": null,
  "format": "ig_carousel",
  "caption": "I swapped my evening serum for two weeks. Here's what changed (and what didn't). Fragrance-free, which my skin needed. #ad #lumenglow @lumen.skincare",
  "hashtags": [
    "ad",
    "lumenglow",
    "skincareroutine"
  ],
  "cta": "Shop the launch",
  "link_url": "https://lumen.example/serum",
  "media": [
    {
      "asset_id": "cmf0med101",
      "url": "https://croud.ai/uploads/ws/slide-1.png",
      "type": "image",
      "width": 1080,
      "height": 1350
    }
  ],
  "status": "archived",
  "ai_generated": true,
  "version": 1,
  "kind": "variant",
  "parent_id": "cmf0crt001",
  "variant_for_account_id": "cmf0acc001",
  "angle": "routine",
  "design_template_id": "cmf0dt0002",
  "caption_template_id": null,
  "variant_status": "replaced",
  "design_id": "cmf0dsn101",
  "created_at": "2026-11-01T09:00:00.000Z",
  "updated_at": "2026-11-01T09:00:00.000Z"
}
Reference

Brand kits

A workspace's visual identity (colors, fonts, logos, handle) applied to designs and unique-post visuals.

GET/v1/brand-kits

List brand kits

The workspace's brand kits, default first. Designs and unique-post visuals use a campaign's kit, otherwise the default.

Scopecreatives:readMCP toollist_brand_kits
Request
curl "https://croud.ai/api/v1/brand-kits" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0bk0001",
      "object": "brand_kit",
      "name": "Lumen",
      "is_default": true,
      "colors": {
        "dark": "#14120f",
        "light": "#f6f3ee",
        "accent": "#d7f25c",
        "accent_ink": "#14120f",
        "secondary": "#8aa6c1"
      },
      "fonts": {
        "display": {
          "family": "Instrument Serif",
          "source": "google"
        },
        "body": {
          "family": "Inter",
          "source": "google"
        },
        "mono": {
          "family": "JetBrains Mono",
          "source": "google"
        }
      },
      "logo_url": "https://croud.ai/uploads/ws/lumen-logo.png",
      "logo_dark_url": null,
      "mark_url": null,
      "handle": "lumen.skincare",
      "website": "lumen.example",
      "footer": null,
      "radius": 24,
      "warnings": [],
      "created_at": "2026-10-20T10:00:00.000Z",
      "updated_at": "2026-10-21T09:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
POST/v1/brand-kits

Create a brand kit

Creates a brand kit. The first kit becomes the default. Fonts must be in the Google font catalog or uploaded in the studio first. Limited by the plan's brandKits.

Scopecreatives:writeMCP toolcreate_brand_kit
Body
namerequired
string
colorsrequired
objectDark and light slide backgrounds, the accent, text on the accent and a second accent
fontsrequired
objectFont for headlines, body text and labels
logo_url
string | nullhttps:// URL or a media library path
logo_dark_url
string | nullLogo for dark backgrounds
mark_url
string | nullSquare icon / avatar
handle
string | nullInstagram handle shown on slides
website
string | null
footer
string | null
radius
integerCorner radius in px (default 24)
is_default
booleanMake this the workspace's default kit
Request
curl -X POST "https://croud.ai/api/v1/brand-kits" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Lumen","colors":{"dark":"#14120f","light":"#f6f3ee","accent":"#d7f25c","accent_ink":"#14120f","secondary":"#8aa6c1"},"fonts":{"display":{"family":"Instrument Serif","source":"google"},"body":{"family":"Inter","source":"google"},"mono":{"family":"JetBrains Mono","source":"google"}},"handle":"lumen.skincare","website":"lumen.example"}'
Response · 201
{
  "id": "cmf0bk0001",
  "object": "brand_kit",
  "name": "Lumen",
  "is_default": true,
  "colors": {
    "dark": "#14120f",
    "light": "#f6f3ee",
    "accent": "#d7f25c",
    "accent_ink": "#14120f",
    "secondary": "#8aa6c1"
  },
  "fonts": {
    "display": {
      "family": "Instrument Serif",
      "source": "google"
    },
    "body": {
      "family": "Inter",
      "source": "google"
    },
    "mono": {
      "family": "JetBrains Mono",
      "source": "google"
    }
  },
  "logo_url": "https://croud.ai/uploads/ws/lumen-logo.png",
  "logo_dark_url": null,
  "mark_url": null,
  "handle": "lumen.skincare",
  "website": "lumen.example",
  "footer": null,
  "radius": 24,
  "warnings": [],
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-21T09:00:00.000Z"
}
GET/v1/brand-kits/{id}

Get a brand kit

Retrieve one brand kit with contrast warnings for its colors.

Scopecreatives:readMCP toolget_brand_kit
Path parameters
idrequired
stringBrand kit ID
Request
curl "https://croud.ai/api/v1/brand-kits/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0bk0001",
  "object": "brand_kit",
  "name": "Lumen",
  "is_default": true,
  "colors": {
    "dark": "#14120f",
    "light": "#f6f3ee",
    "accent": "#d7f25c",
    "accent_ink": "#14120f",
    "secondary": "#8aa6c1"
  },
  "fonts": {
    "display": {
      "family": "Instrument Serif",
      "source": "google"
    },
    "body": {
      "family": "Inter",
      "source": "google"
    },
    "mono": {
      "family": "JetBrains Mono",
      "source": "google"
    }
  },
  "logo_url": "https://croud.ai/uploads/ws/lumen-logo.png",
  "logo_dark_url": null,
  "mark_url": null,
  "handle": "lumen.skincare",
  "website": "lumen.example",
  "footer": null,
  "radius": 24,
  "warnings": [],
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-21T09:00:00.000Z"
}
PATCH/v1/brand-kits/{id}

Update a brand kit

Update fields; omitted fields keep their values (colors and fonts are replaced as a whole). Designs using the kit pick up the change on their next render.

Scopecreatives:writeMCP toolupdate_brand_kit
Path parameters
idrequired
stringBrand kit ID
Body
name
string
colors
objectDark and light slide backgrounds, the accent, text on the accent and a second accent
fonts
objectFont for headlines, body text and labels
logo_url
string | nullhttps:// URL or a media library path
logo_dark_url
string | nullLogo for dark backgrounds
mark_url
string | nullSquare icon / avatar
handle
string | nullInstagram handle shown on slides
website
string | null
footer
string | null
radius
integerCorner radius in px (default 24)
is_default
booleanMake this the workspace's default kit
Request
curl -X PATCH "https://croud.ai/api/v1/brand-kits/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"colors":{"dark":"#14120f","light":"#f6f3ee","accent":"#f2c94c","accent_ink":"#14120f","secondary":"#8aa6c1"}}'
Response · 200
{
  "id": "cmf0bk0001",
  "object": "brand_kit",
  "name": "Lumen",
  "is_default": true,
  "colors": {
    "dark": "#14120f",
    "light": "#f6f3ee",
    "accent": "#d7f25c",
    "accent_ink": "#14120f",
    "secondary": "#8aa6c1"
  },
  "fonts": {
    "display": {
      "family": "Instrument Serif",
      "source": "google"
    },
    "body": {
      "family": "Inter",
      "source": "google"
    },
    "mono": {
      "family": "JetBrains Mono",
      "source": "google"
    }
  },
  "logo_url": "https://croud.ai/uploads/ws/lumen-logo.png",
  "logo_dark_url": null,
  "mark_url": null,
  "handle": "lumen.skincare",
  "website": "lumen.example",
  "footer": null,
  "radius": 24,
  "warnings": [],
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-21T09:00:00.000Z"
}
DELETE/v1/brand-kits/{id}

Delete a brand kit

Deletes a brand kit. Designs and campaigns using it move to the workspace's next kit, which becomes the default if this one was.

Scopecreatives:writeMCP tooldelete_brand_kit
Path parameters
idrequired
stringBrand kit ID
Request
curl -X DELETE "https://croud.ai/api/v1/brand-kits/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0bk0002",
  "object": "brand_kit",
  "deleted": true,
  "moved_to": "cmf0bk0001",
  "designs_moved": 3,
  "campaigns_moved": 1
}
POST/v1/brand-kits/{id}/default

Set the default brand kit

Makes this kit the workspace default. New designs and campaigns without a kit use it.

Scopecreatives:writeMCP toolset_default_brand_kit
Path parameters
idrequired
stringBrand kit ID
Request
curl -X POST "https://croud.ai/api/v1/brand-kits/id_123/default" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0bk0001",
  "object": "brand_kit",
  "name": "Lumen",
  "is_default": true,
  "colors": {
    "dark": "#14120f",
    "light": "#f6f3ee",
    "accent": "#d7f25c",
    "accent_ink": "#14120f",
    "secondary": "#8aa6c1"
  },
  "fonts": {
    "display": {
      "family": "Instrument Serif",
      "source": "google"
    },
    "body": {
      "family": "Inter",
      "source": "google"
    },
    "mono": {
      "family": "JetBrains Mono",
      "source": "google"
    }
  },
  "logo_url": "https://croud.ai/uploads/ws/lumen-logo.png",
  "logo_dark_url": null,
  "mark_url": null,
  "handle": "lumen.skincare",
  "website": "lumen.example",
  "footer": null,
  "radius": 24,
  "warnings": [],
  "created_at": "2026-10-20T10:00:00.000Z",
  "updated_at": "2026-10-21T09:00:00.000Z"
}
Reference

Design studio

Design templates, slide layouts and designs: branded carousels, posts and stories written with AI and exported to images, PDFs or creatives.

GET/v1/design-templates

List design templates

The visual template gallery (system templates plus the workspace's custom ones) with availability after platform, plan and workspace controls. Locked templates (available: false, e.g. above your plan) are listed so you can see what an upgrade unlocks; hidden ones are omitted.

Scopecreatives:readMCP toollist_design_templates
Query parameters
category
stringCategory key, e.g. carousel, product, promo
format
stringOnly templates that support this canvas, e.g. story
source
"system" | "custom"
search
stringMatch on name, description and tags
available_only
boolean | "0" | "1" | "true" | "false"Only templates you can use now
Request
curl "https://croud.ai/api/v1/design-templates" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0dt0001",
      "object": "design_template",
      "key": "myth-vs-fact",
      "source": "system",
      "name": "Myth vs fact",
      "description": "Bust common misconceptions in your niche, one slide at a time.",
      "category": "carousel",
      "tags": [
        "education",
        "myths"
      ],
      "formats": [
        "portrait",
        "square",
        "story"
      ],
      "default_format": "portrait",
      "featured": true,
      "status": "active",
      "available": true,
      "availability": "enabled",
      "restricted_by": null,
      "reason": null,
      "min_plan": null,
      "slide_count": 6,
      "usage_count": 128
    }
  ],
  "categories": [
    {
      "key": "carousel",
      "label": "Educational carousels"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
GET/v1/design-templates/{id}

Get a design template

One template with its definition (style, look, sample slides) and the layouts it offers. Locked templates return only their first slides (definition.preview: true).

Scopecreatives:readMCP toolget_design_template
Path parameters
idrequired
stringDesign template ID
Request
curl "https://croud.ai/api/v1/design-templates/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0dt0001",
  "object": "design_template",
  "key": "myth-vs-fact",
  "source": "system",
  "name": "Myth vs fact",
  "description": "Bust common misconceptions in your niche, one slide at a time.",
  "category": "carousel",
  "tags": [
    "education",
    "myths"
  ],
  "formats": [
    "portrait",
    "square",
    "story"
  ],
  "default_format": "portrait",
  "featured": true,
  "status": "active",
  "available": true,
  "availability": "enabled",
  "restricted_by": null,
  "reason": null,
  "min_plan": null,
  "slide_count": 6,
  "usage_count": 128,
  "definition": {
    "style": {
      "scheme": "dark",
      "emphasis": "accent"
    },
    "look": {
      "colors": {
        "dark": "#14120f",
        "light": "#f6f3ee",
        "accent": "#d7f25c",
        "accent_ink": "#14120f",
        "secondary": "#8aa6c1"
      },
      "fonts": {
        "display": {
          "family": "Instrument Serif",
          "source": "google"
        },
        "body": {
          "family": "Inter",
          "source": "google"
        },
        "mono": {
          "family": "JetBrains Mono",
          "source": "google"
        }
      }
    },
    "slides": [
      {
        "id": "a1b2c3d4e5",
        "layout": "cover",
        "variant": "stack",
        "content": {
          "eyebrow": "Skincare myths",
          "headline": "Niacinamide *myths*, busted",
          "subhead": "Swipe before you buy another serum."
        }
      },
      {
        "id": "f6g7h8i9j0",
        "layout": "list",
        "content": {
          "headline": "What it actually does",
          "items": [
            {
              "title": "Evens tone"
            },
            {
              "title": "Supports the barrier"
            }
          ]
        }
      }
    ],
    "ai": {
      "min_slides": 4,
      "max_slides": 8
    },
    "preview": false
  },
  "layouts": []
}
PATCH/v1/design-templates/{id}

Update a custom design template

Rename one of the workspace's own (custom) design templates or change its description, category or tags. Slides and style stay as saved. System templates can't be edited (404). Keys that can also read creatives get the full gallery entry back.

Scopetemplates:writeMCP toolupdate_design_template
Path parameters
idrequired
stringDesign template ID
Body
name
string
description
string | nullnull or an empty string clears it
category
stringCategory key from categories in GET /v1/design-templates, e.g. carousel, product, promo
tags
string[]Replaces the tags (up to 10)
Request
curl -X PATCH "https://croud.ai/api/v1/design-templates/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Lumen myth buster","description":"Our go-to education carousel","category":"carousel","tags":["education","skincare"]}'
Response · 200
{
  "id": "cmf0dt0001",
  "object": "design_template",
  "key": null,
  "source": "custom",
  "name": "Lumen myth buster",
  "description": "Our go-to education carousel",
  "category": "carousel",
  "tags": [
    "education",
    "skincare"
  ],
  "formats": [
    "portrait",
    "square",
    "story"
  ],
  "default_format": "portrait",
  "featured": false,
  "status": "active",
  "available": true,
  "availability": "enabled",
  "restricted_by": null,
  "reason": null,
  "min_plan": null,
  "slide_count": 6,
  "usage_count": 4
}
GET/v1/layouts

List slide layouts

Every slide layout with its variants and content fields (with soft character limits), plus the canvas formats. Use it to build or edit slides by hand.

Scopecreatives:read or templates:readMCP toollist_layouts
Request
curl "https://croud.ai/api/v1/layouts" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "key": "cover",
      "object": "layout",
      "name": "Cover",
      "description": "Opening slide with a hook headline.",
      "group": "Structure",
      "variants": [
        {
          "key": "stack",
          "label": "Stacked"
        }
      ],
      "fields": [
        {
          "key": "headline",
          "label": "Hook",
          "type": "textarea",
          "max_chars": 60,
          "min_items": null,
          "max_items": null,
          "item_fields": null,
          "ai": true,
          "help": "Wrap words in *asterisks* to emphasize them.",
          "options": null
        }
      ],
      "ai_hint": "The hook."
    }
  ],
  "formats": [
    {
      "key": "portrait",
      "label": "Portrait",
      "ratio": "4:5",
      "width": 1080,
      "height": 1350
    }
  ],
  "has_more": false,
  "next_cursor": null
}
GET/v1/designs

List designs

Designs, most recently edited first. Archived designs are excluded unless status=archived or status=all.

Scopecreatives:readMCP toollist_designs
Query parameters
limit
integerPage size, 1–100 (default 25)
cursor
stringnext_cursor from the previous page
status
"draft" | "ready" | "archived" | "all"
campaign_id
string
template_id
string
brand_kit_id
string
search
stringMatch on name
Request
curl "https://croud.ai/api/v1/designs" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0dsn001",
      "object": "design",
      "name": "Myth vs fact: niacinamide",
      "status": "draft",
      "template_id": "cmf0dt0001",
      "brand_kit_id": "cmf0bk0001",
      "campaign_id": "cmf0cmp001",
      "persona_id": null,
      "content_type": "education",
      "team_id": null,
      "format": "portrait",
      "style": {
        "brand": {
          "handle": "@lumen.skincare"
        }
      },
      "slides": [
        {
          "id": "a1b2c3d4e5",
          "layout": "cover",
          "variant": "stack",
          "content": {
            "eyebrow": "Skincare myths",
            "headline": "Niacinamide *myths*, busted",
            "subhead": "Swipe before you buy another serum."
          }
        },
        {
          "id": "f6g7h8i9j0",
          "layout": "list",
          "content": {
            "headline": "What it actually does",
            "items": [
              {
                "title": "Evens tone"
              },
              {
                "title": "Supports the barrier"
              }
            ]
          }
        }
      ],
      "slide_count": 2,
      "caption": "Three things niacinamide can (and can't) do. #ad",
      "hashtags": [
        "skincare",
        "niacinamide"
      ],
      "ai_assisted": true,
      "thumbnail_url": null,
      "last_exported_at": null,
      "created_at": "2026-10-28T10:00:00.000Z",
      "updated_at": "2026-10-28T10:05:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
POST/v1/designs

Create a design

Creates a design from a template (or blank) with the brand kit applied. Pass brief to have AI write the slides, caption and hashtags right away: the design is created either way, and ai reports whether the AI run succeeded. Locked templates return 402. Limited by the plan's designs.

Scopecreatives:writeMCP toolcreate_design
Body
template_id
string | nullDesign template (see GET /v1/design-templates). Omitted = blank design
name
string
format
"portrait" | "square" | "story" | "landscape" | "wide" | "pin"Canvas: portrait (4:5), square, story (9:16), landscape, wide or pin. Defaults to the template's
brand_kit_id
string | nullBrand kit ID, or template for the template's own look. Omitted = the campaign's kit, then the workspace default
campaign_id
string | null
persona_id
string | null
content_type
string | null
team_id
string | null
slides
object[]Start from these slides instead of the template's
style
objectDesign-level style overrides (scheme, background, headlineFont, emphasis, align, counter, showLogo…). brand holds this design's own brand details (name ≤ 60, handle ≤ 40, website ≤ 80, footer ≤ 80, logoUrl: uploaded or HTTPS image). Each field wins over the brand kit, which wins over the workspace profile (name, Instagram username, website, logo); empty fields render nothing
caption
string | null
hashtags
string[]
brief
stringWrite the slides, caption and hashtags with AI right after creating (needs the ai:generate scope; uses AI credits)
ai
objectOptions for the AI run when brief is given
Request
curl -X POST "https://croud.ai/api/v1/designs" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"template_id":"cmf0dt0001","campaign_id":"cmf0cmp001","format":"portrait","brief":"Three myths about niacinamide, for people new to skincare. Product: Lumen Glow serum."}'
Response · 201
{
  "id": "cmf0dsn001",
  "object": "design",
  "name": "Myth vs fact: niacinamide",
  "status": "draft",
  "template_id": "cmf0dt0001",
  "brand_kit_id": "cmf0bk0001",
  "campaign_id": "cmf0cmp001",
  "persona_id": null,
  "content_type": "education",
  "team_id": null,
  "format": "portrait",
  "style": {
    "brand": {
      "handle": "@lumen.skincare"
    }
  },
  "slides": [
    {
      "id": "a1b2c3d4e5",
      "layout": "cover",
      "variant": "stack",
      "content": {
        "eyebrow": "Skincare myths",
        "headline": "Niacinamide *myths*, busted",
        "subhead": "Swipe before you buy another serum."
      }
    },
    {
      "id": "f6g7h8i9j0",
      "layout": "list",
      "content": {
        "headline": "What it actually does",
        "items": [
          {
            "title": "Evens tone"
          },
          {
            "title": "Supports the barrier"
          }
        ]
      }
    }
  ],
  "slide_count": 2,
  "caption": "Three things niacinamide can (and can't) do. #ad",
  "hashtags": [
    "skincare",
    "niacinamide"
  ],
  "ai_assisted": true,
  "thumbnail_url": null,
  "last_exported_at": null,
  "created_at": "2026-10-28T10:00:00.000Z",
  "updated_at": "2026-10-28T10:05:00.000Z",
  "ai": {
    "ok": true,
    "generation_id": "cmf0gen001",
    "provider": "openrouter",
    "model": "anthropic/claude-sonnet-5.5",
    "fallback_used": false,
    "credits_charged": 8,
    "sandbox": false,
    "used_byok": false,
    "repaired": false,
    "content_type": "education",
    "persona": {
      "id": "cmf0prs101",
      "name": "Practical teacher",
      "platform": true,
      "source": "platform_type"
    }
  }
}
GET/v1/designs/{id}

Get a design

Retrieve one design with its slides.

Scopecreatives:readMCP toolget_design
Path parameters
idrequired
stringDesign ID
Request
curl "https://croud.ai/api/v1/designs/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0dsn001",
  "object": "design",
  "name": "Myth vs fact: niacinamide",
  "status": "draft",
  "template_id": "cmf0dt0001",
  "brand_kit_id": "cmf0bk0001",
  "campaign_id": "cmf0cmp001",
  "persona_id": null,
  "content_type": "education",
  "team_id": null,
  "format": "portrait",
  "style": {
    "brand": {
      "handle": "@lumen.skincare"
    }
  },
  "slides": [
    {
      "id": "a1b2c3d4e5",
      "layout": "cover",
      "variant": "stack",
      "content": {
        "eyebrow": "Skincare myths",
        "headline": "Niacinamide *myths*, busted",
        "subhead": "Swipe before you buy another serum."
      }
    },
    {
      "id": "f6g7h8i9j0",
      "layout": "list",
      "content": {
        "headline": "What it actually does",
        "items": [
          {
            "title": "Evens tone"
          },
          {
            "title": "Supports the barrier"
          }
        ]
      }
    }
  ],
  "slide_count": 2,
  "caption": "Three things niacinamide can (and can't) do. #ad",
  "hashtags": [
    "skincare",
    "niacinamide"
  ],
  "ai_assisted": true,
  "thumbnail_url": null,
  "last_exported_at": null,
  "created_at": "2026-10-28T10:00:00.000Z",
  "updated_at": "2026-10-28T10:05:00.000Z"
}
PATCH/v1/designs/{id}

Update a design

Update fields; omitted fields keep their values and slides replaces all slides. Send expected_updated_at to avoid overwriting someone else's edit (409 on conflict). Changing format must stay within the template's formats.

Scopecreatives:writeMCP toolupdate_design
Path parameters
idrequired
stringDesign ID
Body
name
string
format
"portrait" | "square" | "story" | "landscape" | "wide" | "pin"portrait | square | story | landscape | wide | pin
style
objectDesign-level style overrides (scheme, background, headlineFont, emphasis, align, counter, showLogo…). brand holds this design's own brand details (name ≤ 60, handle ≤ 40, website ≤ 80, footer ≤ 80, logoUrl: uploaded or HTTPS image). Each field wins over the brand kit, which wins over the workspace profile (name, Instagram username, website, logo); empty fields render nothing
slides
object[]Slides: { id, layout, variant?, content, style? } (see GET /v1/layouts for each layout's content fields). Validated server-side
brand_kit_id
string | nullBrand kit ID; null = the template's own look
campaign_id
string | null
persona_id
string | null
content_type
string | null
caption
string | null
hashtags
string[]
status
"draft" | "ready" | "archived"archived hides it and frees a saved-design slot
ai_assisted
booleanMark the copy as AI-written (e.g. you applied a caption from /captions). AI runs set it automatically; it is never cleared
expected_updated_at
stringISO 8601 date-time: the design's updated_at you last read. The write fails with 409 if it changed since
Request
curl -X PATCH "https://croud.ai/api/v1/designs/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"caption":"Three niacinamide myths, busted. #ad","status":"ready","expected_updated_at":"2026-10-28T10:05:00.000Z"}'
Response · 200
{
  "id": "cmf0dsn001",
  "object": "design",
  "name": "Myth vs fact: niacinamide",
  "status": "ready",
  "template_id": "cmf0dt0001",
  "brand_kit_id": "cmf0bk0001",
  "campaign_id": "cmf0cmp001",
  "persona_id": null,
  "content_type": "education",
  "team_id": null,
  "format": "portrait",
  "style": {
    "brand": {
      "handle": "@lumen.skincare"
    }
  },
  "slides": [
    {
      "id": "a1b2c3d4e5",
      "layout": "cover",
      "variant": "stack",
      "content": {
        "eyebrow": "Skincare myths",
        "headline": "Niacinamide *myths*, busted",
        "subhead": "Swipe before you buy another serum."
      }
    },
    {
      "id": "f6g7h8i9j0",
      "layout": "list",
      "content": {
        "headline": "What it actually does",
        "items": [
          {
            "title": "Evens tone"
          },
          {
            "title": "Supports the barrier"
          }
        ]
      }
    }
  ],
  "slide_count": 2,
  "caption": "Three things niacinamide can (and can't) do. #ad",
  "hashtags": [
    "skincare",
    "niacinamide"
  ],
  "ai_assisted": true,
  "thumbnail_url": null,
  "last_exported_at": null,
  "created_at": "2026-10-28T10:00:00.000Z",
  "updated_at": "2026-10-28T10:05:00.000Z"
}
DELETE/v1/designs/{id}

Delete a design

Permanently deletes a design and its export files. Media saved to the library and creatives made from it stay.

Scopecreatives:writeMCP tooldelete_design
Path parameters
idrequired
stringDesign ID
Request
curl -X DELETE "https://croud.ai/api/v1/designs/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0dsn001",
  "object": "design",
  "deleted": true
}
POST/v1/designs/{id}/duplicate

Duplicate a design

Copies a design as a new draft, optionally renamed or for another campaign.

Scopecreatives:writeMCP toolduplicate_design
Path parameters
idrequired
stringDesign ID
Body
name
string
campaign_id
string | nullCampaign for the copy (defaults to the original's)
Request
curl -X POST "https://croud.ai/api/v1/designs/id_123/duplicate" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
Response · 201
{
  "id": "cmf0dsn002",
  "object": "design",
  "name": "Myth vs fact: niacinamide (copy)",
  "status": "draft",
  "template_id": "cmf0dt0001",
  "brand_kit_id": "cmf0bk0001",
  "campaign_id": "cmf0cmp001",
  "persona_id": null,
  "content_type": "education",
  "team_id": null,
  "format": "portrait",
  "style": {
    "brand": {
      "handle": "@lumen.skincare"
    }
  },
  "slides": [
    {
      "id": "a1b2c3d4e5",
      "layout": "cover",
      "variant": "stack",
      "content": {
        "eyebrow": "Skincare myths",
        "headline": "Niacinamide *myths*, busted",
        "subhead": "Swipe before you buy another serum."
      }
    },
    {
      "id": "f6g7h8i9j0",
      "layout": "list",
      "content": {
        "headline": "What it actually does",
        "items": [
          {
            "title": "Evens tone"
          },
          {
            "title": "Supports the barrier"
          }
        ]
      }
    }
  ],
  "slide_count": 2,
  "caption": "Three things niacinamide can (and can't) do. #ad",
  "hashtags": [
    "skincare",
    "niacinamide"
  ],
  "ai_assisted": true,
  "thumbnail_url": null,
  "last_exported_at": null,
  "created_at": "2026-10-28T10:00:00.000Z",
  "updated_at": "2026-10-28T10:05:00.000Z"
}
POST/v1/designs/{id}/generate

Write a design with AI

AI writes the slides, caption and hashtags from a brief, using the template's guidance, the brand kit, the content type's rules (caption length, hashtags, structure, slide count), the persona's voice and the platform style guide. Output that breaks a rule gets one automatic repair; unusable output is refunded. With apply (default) the result is saved together with content_type (and an explicit persona_id); otherwise it's only returned. A design edited meanwhile returns 409 and is refunded. Needs the ai:generate scope as well and uses AI credits.

Scopecreatives:writeMCP toolwrite_design_with_ai
Path parameters
idrequired
stringDesign ID
Body
briefrequired
stringWhat the design should say
persona_id
string | nullVoice (workspace or platform persona). Omitted = the design's persona, else the voice for the content type, else the workspace default; null = none
content_type
string | nullContent type for this run (default: the design's). Saved to the design when the result is applied
language
stringLanguage code, e.g. en, de
slide_count
integer
extra_instructions
string
model
stringAI model for this run: a ref from GET /v1/ai/models, e.g. "openrouter:anthropic/claude-sonnet-5.5". Omitted = automatic routing. Credits use that model's multiplier
apply
booleanSave into the design (default true)
expected_updated_at
stringISO 8601 date-time: the design's updated_at you last read. The write fails with 409 if it changed since
Request
curl -X POST "https://croud.ai/api/v1/designs/id_123/generate" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"brief":"Three myths about niacinamide, for people new to skincare.","content_type":"education","slide_count":5,"apply":true}'
Response · 200
{
  "object": "design_generation",
  "design": {
    "id": "cmf0dsn001",
    "object": "design",
    "name": "Myth vs fact: niacinamide",
    "status": "draft",
    "template_id": "cmf0dt0001",
    "brand_kit_id": "cmf0bk0001",
    "campaign_id": "cmf0cmp001",
    "persona_id": null,
    "content_type": "education",
    "team_id": null,
    "format": "portrait",
    "style": {
      "brand": {
        "handle": "@lumen.skincare"
      }
    },
    "slides": [
      {
        "id": "a1b2c3d4e5",
        "layout": "cover",
        "variant": "stack",
        "content": {
          "eyebrow": "Skincare myths",
          "headline": "Niacinamide *myths*, busted",
          "subhead": "Swipe before you buy another serum."
        }
      },
      {
        "id": "f6g7h8i9j0",
        "layout": "list",
        "content": {
          "headline": "What it actually does",
          "items": [
            {
              "title": "Evens tone"
            },
            {
              "title": "Supports the barrier"
            }
          ]
        }
      }
    ],
    "slide_count": 2,
    "caption": "Three things niacinamide can (and can't) do. #ad",
    "hashtags": [
      "skincare",
      "niacinamide"
    ],
    "ai_assisted": true,
    "thumbnail_url": null,
    "last_exported_at": null,
    "created_at": "2026-10-28T10:00:00.000Z",
    "updated_at": "2026-10-28T10:05:00.000Z"
  },
  "slides": [
    {
      "id": "a1b2c3d4e5",
      "layout": "cover",
      "variant": "stack",
      "content": {
        "eyebrow": "Skincare myths",
        "headline": "Niacinamide *myths*, busted",
        "subhead": "Swipe before you buy another serum."
      }
    },
    {
      "id": "f6g7h8i9j0",
      "layout": "list",
      "content": {
        "headline": "What it actually does",
        "items": [
          {
            "title": "Evens tone"
          },
          {
            "title": "Supports the barrier"
          }
        ]
      }
    }
  ],
  "caption": "Three things niacinamide can (and can't) do. #ad",
  "hashtags": [
    "skincare",
    "niacinamide"
  ],
  "applied": true,
  "generation_id": "cmf0gen001",
  "provider": "openrouter",
  "model": "anthropic/claude-sonnet-5.5",
  "fallback_used": false,
  "credits_charged": 8,
  "sandbox": false,
  "used_byok": false,
  "repaired": false,
  "content_type": "education",
  "persona": {
    "id": "cmf0prs101",
    "name": "Practical teacher",
    "platform": true,
    "source": "platform_type"
  }
}
POST/v1/designs/{id}/rewrite

Rewrite slides with AI

Rewrites some slides in place (same layouts, images and style) with a quick action (shorter, punchier, casual, fit to fix overflowing text) and/or an instruction; caption: true rewrites the caption and hashtags too (default when every slide is rewritten). One slide is billed as a design_edit, several as design. With apply (default) the result is saved; 409 if the design changed meanwhile (refunded). Needs the ai:generate scope as well.

Scopecreatives:writeMCP toolrewrite_design_slides
Path parameters
idrequired
stringDesign ID
Body
slides
integer[]0-based slide indexes (default all)
action
"shorter" | "punchier" | "casual" | "fit"shorter | punchier | casual | fit
instruction
stringWhat to change, e.g. "Lead with the price"
brief
stringFacts the rewrite may use
caption
boolean
persona_id
string | nullVoice (workspace or platform persona). Omitted = the design's persona, else the voice for the content type, else the workspace default; null = none
content_type
string | nullContent type for this run (default: the design's). Saved to the design when the result is applied
language
stringLanguage code, e.g. en, de
model
stringAI model for this run: a ref from GET /v1/ai/models, e.g. "openrouter:anthropic/claude-sonnet-5.5". Omitted = automatic routing. Credits use that model's multiplier
apply
booleanSave into the design (default true)
expected_updated_at
stringISO 8601 date-time: the design's updated_at you last read. The write fails with 409 if it changed since
Request
curl -X POST "https://croud.ai/api/v1/designs/id_123/rewrite" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"slides":[2],"action":"shorter"}'
Response · 200
{
  "object": "design_rewrite",
  "design": {
    "id": "cmf0dsn001",
    "object": "design",
    "name": "Myth vs fact: niacinamide",
    "status": "draft",
    "template_id": "cmf0dt0001",
    "brand_kit_id": "cmf0bk0001",
    "campaign_id": "cmf0cmp001",
    "persona_id": null,
    "content_type": "education",
    "team_id": null,
    "format": "portrait",
    "style": {
      "brand": {
        "handle": "@lumen.skincare"
      }
    },
    "slides": [
      {
        "id": "a1b2c3d4e5",
        "layout": "cover",
        "variant": "stack",
        "content": {
          "eyebrow": "Skincare myths",
          "headline": "Niacinamide *myths*, busted",
          "subhead": "Swipe before you buy another serum."
        }
      },
      {
        "id": "f6g7h8i9j0",
        "layout": "list",
        "content": {
          "headline": "What it actually does",
          "items": [
            {
              "title": "Evens tone"
            },
            {
              "title": "Supports the barrier"
            }
          ]
        }
      }
    ],
    "slide_count": 2,
    "caption": "Three things niacinamide can (and can't) do. #ad",
    "hashtags": [
      "skincare",
      "niacinamide"
    ],
    "ai_assisted": true,
    "thumbnail_url": null,
    "last_exported_at": null,
    "created_at": "2026-10-28T10:00:00.000Z",
    "updated_at": "2026-10-28T10:05:00.000Z"
  },
  "slides": [
    {
      "id": "a1b2c3d4e5",
      "layout": "cover",
      "variant": "stack",
      "content": {
        "eyebrow": "Skincare myths",
        "headline": "Niacinamide *myths*, busted",
        "subhead": "Swipe before you buy another serum."
      }
    },
    {
      "id": "f6g7h8i9j0",
      "layout": "list",
      "content": {
        "headline": "What it actually does",
        "items": [
          {
            "title": "Evens tone"
          },
          {
            "title": "Supports the barrier"
          }
        ]
      }
    }
  ],
  "rewritten": [
    1
  ],
  "caption": null,
  "hashtags": null,
  "applied": true,
  "generation_id": "cmf0gen001",
  "provider": "openrouter",
  "model": "anthropic/claude-sonnet-5.5",
  "fallback_used": false,
  "credits_charged": 2,
  "sandbox": false,
  "used_byok": false,
  "repaired": false,
  "content_type": "education",
  "persona": {
    "id": "cmf0prs101",
    "name": "Practical teacher",
    "platform": true,
    "source": "platform_type"
  }
}
POST/v1/designs/{id}/captions

Caption options for a design

AI writes caption options (default 3, each with hashtags) for the design's current slides, following its content type, persona and the style guide. Nothing is saved: pick one and PATCH it into the design. Billed as one design_edit. Needs the ai:generate scope as well.

Scopecreatives:writeMCP tooldesign_caption_options
Path parameters
idrequired
stringDesign ID
Body
count
integerDefault 3
brief
stringExtra facts for the caption
instruction
string
persona_id
string | nullVoice (workspace or platform persona). Omitted = the design's persona, else the voice for the content type, else the workspace default; null = none
content_type
string | nullContent type for this run (default: the design's). Saved to the design when the result is applied
language
stringLanguage code, e.g. en, de
model
stringAI model for this run: a ref from GET /v1/ai/models, e.g. "openrouter:anthropic/claude-sonnet-5.5". Omitted = automatic routing. Credits use that model's multiplier
Request
curl -X POST "https://croud.ai/api/v1/designs/id_123/captions" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"count":3}'
Response · 200
{
  "object": "design_captions",
  "design_id": "cmf0dsn001",
  "options": [
    {
      "caption": "Niacinamide won't fix everything. Here's what it does do.\n\nSave this before your next serum haul.",
      "hashtags": [
        "niacinamide",
        "skincaretips"
      ]
    },
    {
      "caption": "3 niacinamide myths we hear every week, and what the research says.\n\nSave it for later.",
      "hashtags": [
        "niacinamide",
        "skincaremyths"
      ]
    }
  ],
  "generation_id": "cmf0gen001",
  "provider": "openrouter",
  "model": "anthropic/claude-sonnet-5.5",
  "fallback_used": false,
  "credits_charged": 2,
  "sandbox": false,
  "used_byok": false,
  "repaired": false,
  "content_type": "education",
  "persona": {
    "id": "cmf0prs101",
    "name": "Practical teacher",
    "platform": true,
    "source": "platform_type"
  }
}
POST/v1/designs/{id}/exports

Export a design

Renders slides to PNG, JPG, a ZIP of images or a PDF. Usually finishes within the request (status: done); on deployments with a render worker it returns queued — poll GET /v1/designs/{id}/exports/{export_id} or pass wait: true. save_to_library also stores the images in the media library. Counts toward the plan's monthly designExportsPerMonth; designs from templates above your plan export with a watermark. Files not saved to the library expire after 7 days. Emits design.exported.

Scopecreatives:writeMCP toolexport_design
Path parameters
idrequired
stringDesign ID
Body
kind
"png" | "jpg" | "pdf" | "zip"Default png
image_type
"png" | "jpg"Image type inside a zip
slides
integer[]0-based slide indexes (default all)
scale
number2 = double resolution
save_to_library
boolean
folder
stringMedia library folder for saved images
wait
booleanWait up to 60 seconds for a queued export to finish
Request
curl -X POST "https://croud.ai/api/v1/designs/id_123/exports" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"kind":"png","scale":1,"save_to_library":true}'
Response · 201
{
  "id": "cmf0dex001",
  "object": "design_export",
  "design_id": "cmf0dsn001",
  "status": "done",
  "kind": "png",
  "error": null,
  "warnings": [],
  "watermark": false,
  "slide_count": 2,
  "download_url": "https://croud.ai/uploads/ws/design-cmf0dsn001-1.png",
  "files": [
    {
      "url": "https://croud.ai/uploads/ws/design-cmf0dsn001-1.png",
      "filename": "myth-vs-fact-1.png",
      "mime_type": "image/png",
      "byte_size": 412331,
      "width": 1080,
      "height": 1350,
      "media_id": null
    },
    {
      "url": "https://croud.ai/uploads/ws/design-cmf0dsn001-2.png",
      "filename": "myth-vs-fact-2.png",
      "mime_type": "image/png",
      "byte_size": 398112,
      "width": 1080,
      "height": 1350,
      "media_id": null
    }
  ],
  "media_ids": [],
  "created_at": "2026-10-28T10:06:00.000Z",
  "finished_at": "2026-10-28T10:06:04.000Z",
  "expires_at": "2026-11-04T10:06:04.000Z"
}
GET/v1/designs/{id}/exports

List a design's exports

The design's latest exports, newest first.

Scopecreatives:readMCP toollist_design_exports
Path parameters
idrequired
stringDesign ID
Query parameters
limit
integer
Request
curl "https://croud.ai/api/v1/designs/id_123/exports" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0dex001",
      "object": "design_export",
      "design_id": "cmf0dsn001",
      "status": "done",
      "kind": "png",
      "error": null,
      "warnings": [],
      "watermark": false,
      "slide_count": 2,
      "download_url": "https://croud.ai/uploads/ws/design-cmf0dsn001-1.png",
      "files": [
        {
          "url": "https://croud.ai/uploads/ws/design-cmf0dsn001-1.png",
          "filename": "myth-vs-fact-1.png",
          "mime_type": "image/png",
          "byte_size": 412331,
          "width": 1080,
          "height": 1350,
          "media_id": null
        },
        {
          "url": "https://croud.ai/uploads/ws/design-cmf0dsn001-2.png",
          "filename": "myth-vs-fact-2.png",
          "mime_type": "image/png",
          "byte_size": 398112,
          "width": 1080,
          "height": 1350,
          "media_id": null
        }
      ],
      "media_ids": [],
      "created_at": "2026-10-28T10:06:00.000Z",
      "finished_at": "2026-10-28T10:06:04.000Z",
      "expires_at": "2026-11-04T10:06:04.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
GET/v1/designs/{id}/exports/{export_id}

Get an export

Status of one export: queued, rendering, done, failed or expired. Files and URLs are present once it's done.

Scopecreatives:readMCP toolget_design_export
Path parameters
idrequired
stringDesign ID
export_idrequired
stringExport ID
Request
curl "https://croud.ai/api/v1/designs/id_123/exports/export_id" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0dex001",
  "object": "design_export",
  "design_id": "cmf0dsn001",
  "status": "done",
  "kind": "png",
  "error": null,
  "warnings": [],
  "watermark": false,
  "slide_count": 2,
  "download_url": "https://croud.ai/uploads/ws/design-cmf0dsn001-1.png",
  "files": [
    {
      "url": "https://croud.ai/uploads/ws/design-cmf0dsn001-1.png",
      "filename": "myth-vs-fact-1.png",
      "mime_type": "image/png",
      "byte_size": 412331,
      "width": 1080,
      "height": 1350,
      "media_id": null
    },
    {
      "url": "https://croud.ai/uploads/ws/design-cmf0dsn001-2.png",
      "filename": "myth-vs-fact-2.png",
      "mime_type": "image/png",
      "byte_size": 398112,
      "width": 1080,
      "height": 1350,
      "media_id": null
    }
  ],
  "media_ids": [],
  "created_at": "2026-10-28T10:06:00.000Z",
  "finished_at": "2026-10-28T10:06:04.000Z",
  "expires_at": "2026-11-04T10:06:04.000Z"
}
POST/v1/designs/{id}/creative

Save a design as a creative

Renders the slides into the media library (counts as one export) and creates a draft creative linked to the design, with its caption and hashtags. Story designs become ig_story, one-slide portrait or square designs ig_feed_image, several slides ig_carousel.

Scopecreatives:writeMCP toolsave_design_as_creative
Path parameters
idrequired
stringDesign ID
Body
campaign_id
string | nullCampaign for the creative (defaults to the design's)
format
"ig_feed_image" | "ig_carousel" | "ig_story"Defaults from the design's canvas and slide count. ig_feed_image uses the first slide
name
string
Request
curl -X POST "https://croud.ai/api/v1/designs/id_123/creative" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
Response · 201
{
  "object": "design_creative",
  "design_id": "cmf0dsn001",
  "creative": {
    "id": "cmf0crt009",
    "object": "creative",
    "name": "Myth vs fact: niacinamide",
    "format": "ig_carousel",
    "status": "draft",
    "design_id": "cmf0dsn001"
  },
  "media": [
    {
      "asset_id": "cmf0med001",
      "url": "https://croud.ai/uploads/ws/slide-1.png",
      "type": "image",
      "width": 1080,
      "height": 1350
    }
  ]
}
Reference

Placements

Ad slots on creator accounts: the review inbox for creators and delivery tracking for advertisers.

GET/v1/placements

List placements

Placements are individual ad slots: one creative on one creator account for one campaign. Use side=creator for ad requests on your connected accounts and side=advertiser for placements of your campaigns. Newest first. Campaigns with unique posts start each placement in drafting while its post is written and reviewed (pending_status is the status it moves to next); creators see creative: null until it's ready.

Scopeplacements:readMCP toollist_placements
Query parameters
limit
integerPage size, 1–100 (default 25)
cursor
stringnext_cursor from the previous page
siderequired
"creator" | "advertiser"creator = requests on your accounts; advertiser = placements of your campaigns
status
"drafting" | "pending_approval" | "pending_advertiser" | "changes_requested" | "approved" | "rejected" | "scheduled" | "publishing" | "published" | "disputed" | "completed" | "removed_early" | "failed" | "canceled" | "expired"[] | stringComma-separated statuses, e.g. pending_approval,changes_requested
campaign_id
stringOnly placements of this campaign
account_id
stringOnly placements on this account
origin
"matched" | "open" | "direct"matched (campaign targeting), open (accepted open campaign) or direct (hand-picked request)
Request
curl "https://croud.ai/api/v1/placements?side=creator" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0plc001",
      "object": "placement",
      "side": "creator",
      "status": "pending_approval",
      "origin": "matched",
      "price_cents": 45000,
      "platform_fee_cents": 4500,
      "net_payout_cents": 40500,
      "currency": "USD",
      "campaign": {
        "id": "cmf0cmp001",
        "name": "Autumn glow launch",
        "type": "targeted",
        "objective": "launch",
        "category": "beauty",
        "advertiser": {
          "id": "cmf0ws0001",
          "name": "Lumen Skincare",
          "verified": true
        },
        "start_date": "2026-11-01T00:00:00.000Z",
        "end_date": "2026-11-30T00:00:00.000Z"
      },
      "pending_status": null,
      "account": {
        "id": "cmf0acc001",
        "object": "account",
        "platform": "instagram",
        "username": "maya.creates",
        "display_name": "Maya",
        "avatar_url": null,
        "followers": 48200,
        "engagement_rate": 4.1,
        "country": "US"
      },
      "creative": {
        "id": "cmf0crt001",
        "object": "creative",
        "name": "Serum reel",
        "campaign_id": "cmf0cmp001",
        "template_id": null,
        "persona_id": null,
        "format": "ig_reel",
        "caption": "Glow season is here. #ad",
        "hashtags": [
          "#ad",
          "#skincare"
        ],
        "cta": "Shop now",
        "link_url": "https://lumen.example/serum",
        "media": [],
        "status": "ready",
        "ai_generated": false,
        "version": 1,
        "kind": "standard",
        "parent_id": null,
        "variant_for_account_id": null,
        "angle": null,
        "design_template_id": null,
        "caption_template_id": null,
        "variant_status": null,
        "design_id": null,
        "created_at": "2026-10-20T10:00:00.000Z",
        "updated_at": "2026-10-20T10:00:00.000Z"
      },
      "is_collab": false,
      "collab_handles": [],
      "collab_price_cents": 0,
      "brief": null,
      "requested_publish_at": null,
      "negotiation": {
        "offer_price_cents": null,
        "counter_price_cents": null,
        "rounds": 0
      },
      "scheduled_at": null,
      "published_at": null,
      "completed_at": null,
      "expires_at": "2026-10-30T10:00:00.000Z",
      "permalink": null,
      "auto_approved": false,
      "decision_reason": null,
      "decided_at": null,
      "failure_reason": null,
      "created_at": "2026-10-28T10:00:00.000Z",
      "updated_at": "2026-10-28T10:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
GET/v1/placements/{id}

Get a placement

Retrieve a placement with its campaign, account and creative. Works from either side of the marketplace.

Scopeplacements:readMCP toolget_placement
Path parameters
idrequired
stringPlacement ID
Query parameters
side
"creator" | "advertiser"Disambiguate when the workspace is on both sides
Request
curl "https://croud.ai/api/v1/placements/plc_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0plc001",
  "object": "placement",
  "side": "creator",
  "status": "pending_approval",
  "origin": "matched",
  "price_cents": 45000,
  "platform_fee_cents": 4500,
  "net_payout_cents": 40500,
  "currency": "USD",
  "campaign": {
    "id": "cmf0cmp001",
    "name": "Autumn glow launch",
    "type": "targeted",
    "objective": "launch",
    "category": "beauty",
    "advertiser": {
      "id": "cmf0ws0001",
      "name": "Lumen Skincare",
      "verified": true
    },
    "start_date": "2026-11-01T00:00:00.000Z",
    "end_date": "2026-11-30T00:00:00.000Z"
  },
  "pending_status": null,
  "account": {
    "id": "cmf0acc001",
    "object": "account",
    "platform": "instagram",
    "username": "maya.creates",
    "display_name": "Maya",
    "avatar_url": null,
    "followers": 48200,
    "engagement_rate": 4.1,
    "country": "US"
  },
  "creative": {
    "id": "cmf0crt001",
    "object": "creative",
    "name": "Serum reel",
    "campaign_id": "cmf0cmp001",
    "template_id": null,
    "persona_id": null,
    "format": "ig_reel",
    "caption": "Glow season is here. #ad",
    "hashtags": [
      "#ad",
      "#skincare"
    ],
    "cta": "Shop now",
    "link_url": "https://lumen.example/serum",
    "media": [],
    "status": "ready",
    "ai_generated": false,
    "version": 1,
    "kind": "standard",
    "parent_id": null,
    "variant_for_account_id": null,
    "angle": null,
    "design_template_id": null,
    "caption_template_id": null,
    "variant_status": null,
    "design_id": null,
    "created_at": "2026-10-20T10:00:00.000Z",
    "updated_at": "2026-10-20T10:00:00.000Z"
  },
  "is_collab": false,
  "collab_handles": [],
  "collab_price_cents": 0,
  "brief": null,
  "requested_publish_at": null,
  "negotiation": {
    "offer_price_cents": null,
    "counter_price_cents": null,
    "rounds": 0
  },
  "scheduled_at": null,
  "published_at": null,
  "completed_at": null,
  "expires_at": "2026-10-30T10:00:00.000Z",
  "permalink": null,
  "auto_approved": false,
  "decision_reason": null,
  "decided_at": null,
  "failure_reason": null,
  "created_at": "2026-10-28T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z"
}
POST/v1/placements/{id}/approve

Approve a placement

Creator side. Approves a pending_approval placement (including direct requests at the advertiser's current offer), reserves the advertiser's funds and schedules it in the next slot allowed by the account's pacing rules. If the advertiser's wallet is short, the placement stays pending_approval with pending_status: "awaiting_funds" and is scheduled automatically when they add funds.

Scopeplacements:writeMCP toolapprove_placement
Path parameters
idrequired
stringPlacement ID
Request
curl -X POST "https://croud.ai/api/v1/placements/plc_123/approve" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0plc001",
  "object": "placement",
  "side": "creator",
  "status": "scheduled",
  "origin": "matched",
  "price_cents": 45000,
  "platform_fee_cents": 4500,
  "net_payout_cents": 40500,
  "currency": "USD",
  "campaign": {
    "id": "cmf0cmp001",
    "name": "Autumn glow launch",
    "type": "targeted",
    "objective": "launch",
    "category": "beauty",
    "advertiser": {
      "id": "cmf0ws0001",
      "name": "Lumen Skincare",
      "verified": true
    },
    "start_date": "2026-11-01T00:00:00.000Z",
    "end_date": "2026-11-30T00:00:00.000Z"
  },
  "pending_status": null,
  "account": {
    "id": "cmf0acc001",
    "object": "account",
    "platform": "instagram",
    "username": "maya.creates",
    "display_name": "Maya",
    "avatar_url": null,
    "followers": 48200,
    "engagement_rate": 4.1,
    "country": "US"
  },
  "creative": {
    "id": "cmf0crt001",
    "object": "creative",
    "name": "Serum reel",
    "campaign_id": "cmf0cmp001",
    "template_id": null,
    "persona_id": null,
    "format": "ig_reel",
    "caption": "Glow season is here. #ad",
    "hashtags": [
      "#ad",
      "#skincare"
    ],
    "cta": "Shop now",
    "link_url": "https://lumen.example/serum",
    "media": [],
    "status": "ready",
    "ai_generated": false,
    "version": 1,
    "kind": "standard",
    "parent_id": null,
    "variant_for_account_id": null,
    "angle": null,
    "design_template_id": null,
    "caption_template_id": null,
    "variant_status": null,
    "design_id": null,
    "created_at": "2026-10-20T10:00:00.000Z",
    "updated_at": "2026-10-20T10:00:00.000Z"
  },
  "is_collab": false,
  "collab_handles": [],
  "collab_price_cents": 0,
  "brief": null,
  "requested_publish_at": null,
  "negotiation": {
    "offer_price_cents": null,
    "counter_price_cents": null,
    "rounds": 0
  },
  "scheduled_at": "2026-11-02T15:00:00.000Z",
  "published_at": null,
  "completed_at": null,
  "expires_at": "2026-10-30T10:00:00.000Z",
  "permalink": null,
  "auto_approved": false,
  "decision_reason": null,
  "decided_at": "2026-10-28T11:00:00.000Z",
  "failure_reason": null,
  "created_at": "2026-10-28T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z"
}
POST/v1/placements/{id}/reject

Reject a placement

Creator side. Declines a pending placement; the reason is shared with the advertiser and any reserved funds are released.

Scopeplacements:writeMCP toolreject_placement
Path parameters
idrequired
stringPlacement ID
Body
reasonrequired
stringWhy you're declining (shown to the advertiser)
Request
curl -X POST "https://croud.ai/api/v1/placements/plc_123/reject" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason":"Not a fit for my audience"}'
Response · 200
{
  "id": "cmf0plc001",
  "object": "placement",
  "side": "creator",
  "status": "rejected",
  "origin": "matched",
  "price_cents": 45000,
  "platform_fee_cents": 4500,
  "net_payout_cents": 40500,
  "currency": "USD",
  "campaign": {
    "id": "cmf0cmp001",
    "name": "Autumn glow launch",
    "type": "targeted",
    "objective": "launch",
    "category": "beauty",
    "advertiser": {
      "id": "cmf0ws0001",
      "name": "Lumen Skincare",
      "verified": true
    },
    "start_date": "2026-11-01T00:00:00.000Z",
    "end_date": "2026-11-30T00:00:00.000Z"
  },
  "pending_status": null,
  "account": {
    "id": "cmf0acc001",
    "object": "account",
    "platform": "instagram",
    "username": "maya.creates",
    "display_name": "Maya",
    "avatar_url": null,
    "followers": 48200,
    "engagement_rate": 4.1,
    "country": "US"
  },
  "creative": {
    "id": "cmf0crt001",
    "object": "creative",
    "name": "Serum reel",
    "campaign_id": "cmf0cmp001",
    "template_id": null,
    "persona_id": null,
    "format": "ig_reel",
    "caption": "Glow season is here. #ad",
    "hashtags": [
      "#ad",
      "#skincare"
    ],
    "cta": "Shop now",
    "link_url": "https://lumen.example/serum",
    "media": [],
    "status": "ready",
    "ai_generated": false,
    "version": 1,
    "kind": "standard",
    "parent_id": null,
    "variant_for_account_id": null,
    "angle": null,
    "design_template_id": null,
    "caption_template_id": null,
    "variant_status": null,
    "design_id": null,
    "created_at": "2026-10-20T10:00:00.000Z",
    "updated_at": "2026-10-20T10:00:00.000Z"
  },
  "is_collab": false,
  "collab_handles": [],
  "collab_price_cents": 0,
  "brief": null,
  "requested_publish_at": null,
  "negotiation": {
    "offer_price_cents": null,
    "counter_price_cents": null,
    "rounds": 0
  },
  "scheduled_at": null,
  "published_at": null,
  "completed_at": null,
  "expires_at": "2026-10-30T10:00:00.000Z",
  "permalink": null,
  "auto_approved": false,
  "decision_reason": "Not a fit for my audience",
  "decided_at": null,
  "failure_reason": null,
  "created_at": "2026-10-28T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z"
}
POST/v1/placements/{id}/request-changes

Request changes

Creator side. Sends a pending_approval placement back to the advertiser with requested edits. The advertiser resubmits it after updating the creative.

Scopeplacements:writeMCP toolrequest_placement_changes
Path parameters
idrequired
stringPlacement ID
Body
messagerequired
stringWhat should change
Request
curl -X POST "https://croud.ai/api/v1/placements/plc_123/request-changes" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message":"Please add #ad at the start of the caption"}'
Response · 200
{
  "id": "cmf0plc001",
  "object": "placement",
  "side": "creator",
  "status": "changes_requested",
  "origin": "matched",
  "price_cents": 45000,
  "platform_fee_cents": 4500,
  "net_payout_cents": 40500,
  "currency": "USD",
  "campaign": {
    "id": "cmf0cmp001",
    "name": "Autumn glow launch",
    "type": "targeted",
    "objective": "launch",
    "category": "beauty",
    "advertiser": {
      "id": "cmf0ws0001",
      "name": "Lumen Skincare",
      "verified": true
    },
    "start_date": "2026-11-01T00:00:00.000Z",
    "end_date": "2026-11-30T00:00:00.000Z"
  },
  "pending_status": null,
  "account": {
    "id": "cmf0acc001",
    "object": "account",
    "platform": "instagram",
    "username": "maya.creates",
    "display_name": "Maya",
    "avatar_url": null,
    "followers": 48200,
    "engagement_rate": 4.1,
    "country": "US"
  },
  "creative": {
    "id": "cmf0crt001",
    "object": "creative",
    "name": "Serum reel",
    "campaign_id": "cmf0cmp001",
    "template_id": null,
    "persona_id": null,
    "format": "ig_reel",
    "caption": "Glow season is here. #ad",
    "hashtags": [
      "#ad",
      "#skincare"
    ],
    "cta": "Shop now",
    "link_url": "https://lumen.example/serum",
    "media": [],
    "status": "ready",
    "ai_generated": false,
    "version": 1,
    "kind": "standard",
    "parent_id": null,
    "variant_for_account_id": null,
    "angle": null,
    "design_template_id": null,
    "caption_template_id": null,
    "variant_status": null,
    "design_id": null,
    "created_at": "2026-10-20T10:00:00.000Z",
    "updated_at": "2026-10-20T10:00:00.000Z"
  },
  "is_collab": false,
  "collab_handles": [],
  "collab_price_cents": 0,
  "brief": null,
  "requested_publish_at": null,
  "negotiation": {
    "offer_price_cents": null,
    "counter_price_cents": null,
    "rounds": 0
  },
  "scheduled_at": null,
  "published_at": null,
  "completed_at": null,
  "expires_at": "2026-10-30T10:00:00.000Z",
  "permalink": null,
  "auto_approved": false,
  "decision_reason": "Please add #ad at the start of the caption",
  "decided_at": null,
  "failure_reason": null,
  "created_at": "2026-10-28T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z"
}
POST/v1/placements/{id}/resubmit

Resubmit a placement

Advertiser side. After updating the creative, send a changes_requested placement back to the creator for review.

Scopecampaigns:writeMCP toolresubmit_placement
Path parameters
idrequired
stringPlacement ID
Body
note
stringOptional note to the creator
Request
curl -X POST "https://croud.ai/api/v1/placements/plc_123/resubmit" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"note":"Moved #ad to the first line."}'
Response · 200
{
  "id": "cmf0plc001",
  "object": "placement",
  "side": "advertiser",
  "status": "pending_approval",
  "origin": "matched",
  "price_cents": 45000,
  "platform_fee_cents": 4500,
  "net_payout_cents": 40500,
  "currency": "USD",
  "campaign": {
    "id": "cmf0cmp001",
    "name": "Autumn glow launch",
    "type": "targeted",
    "objective": "launch",
    "category": "beauty",
    "advertiser": {
      "id": "cmf0ws0001",
      "name": "Lumen Skincare",
      "verified": true
    },
    "start_date": "2026-11-01T00:00:00.000Z",
    "end_date": "2026-11-30T00:00:00.000Z"
  },
  "pending_status": null,
  "account": {
    "id": "cmf0acc001",
    "object": "account",
    "platform": "instagram",
    "username": "maya.creates",
    "display_name": "Maya",
    "avatar_url": null,
    "followers": 48200,
    "engagement_rate": 4.1,
    "country": "US"
  },
  "creative": {
    "id": "cmf0crt001",
    "object": "creative",
    "name": "Serum reel",
    "campaign_id": "cmf0cmp001",
    "template_id": null,
    "persona_id": null,
    "format": "ig_reel",
    "caption": "Glow season is here. #ad",
    "hashtags": [
      "#ad",
      "#skincare"
    ],
    "cta": "Shop now",
    "link_url": "https://lumen.example/serum",
    "media": [],
    "status": "ready",
    "ai_generated": false,
    "version": 1,
    "kind": "standard",
    "parent_id": null,
    "variant_for_account_id": null,
    "angle": null,
    "design_template_id": null,
    "caption_template_id": null,
    "variant_status": null,
    "design_id": null,
    "created_at": "2026-10-20T10:00:00.000Z",
    "updated_at": "2026-10-20T10:00:00.000Z"
  },
  "is_collab": false,
  "collab_handles": [],
  "collab_price_cents": 0,
  "brief": null,
  "requested_publish_at": null,
  "negotiation": {
    "offer_price_cents": null,
    "counter_price_cents": null,
    "rounds": 0
  },
  "scheduled_at": null,
  "published_at": null,
  "completed_at": null,
  "expires_at": "2026-10-30T10:00:00.000Z",
  "permalink": null,
  "auto_approved": false,
  "decision_reason": null,
  "decided_at": null,
  "failure_reason": null,
  "created_at": "2026-10-28T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z"
}
POST/v1/placements/{id}/cancel

Cancel a placement

Advertiser side. Cancels a placement that hasn't been published yet and releases its reserved funds.

Scopecampaigns:writeMCP toolcancel_placement
Path parameters
idrequired
stringPlacement ID
Request
curl -X POST "https://croud.ai/api/v1/placements/plc_123/cancel" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0plc001",
  "object": "placement",
  "side": "advertiser",
  "status": "canceled",
  "origin": "matched",
  "price_cents": 45000,
  "platform_fee_cents": 4500,
  "net_payout_cents": 40500,
  "currency": "USD",
  "campaign": {
    "id": "cmf0cmp001",
    "name": "Autumn glow launch",
    "type": "targeted",
    "objective": "launch",
    "category": "beauty",
    "advertiser": {
      "id": "cmf0ws0001",
      "name": "Lumen Skincare",
      "verified": true
    },
    "start_date": "2026-11-01T00:00:00.000Z",
    "end_date": "2026-11-30T00:00:00.000Z"
  },
  "pending_status": null,
  "account": {
    "id": "cmf0acc001",
    "object": "account",
    "platform": "instagram",
    "username": "maya.creates",
    "display_name": "Maya",
    "avatar_url": null,
    "followers": 48200,
    "engagement_rate": 4.1,
    "country": "US"
  },
  "creative": {
    "id": "cmf0crt001",
    "object": "creative",
    "name": "Serum reel",
    "campaign_id": "cmf0cmp001",
    "template_id": null,
    "persona_id": null,
    "format": "ig_reel",
    "caption": "Glow season is here. #ad",
    "hashtags": [
      "#ad",
      "#skincare"
    ],
    "cta": "Shop now",
    "link_url": "https://lumen.example/serum",
    "media": [],
    "status": "ready",
    "ai_generated": false,
    "version": 1,
    "kind": "standard",
    "parent_id": null,
    "variant_for_account_id": null,
    "angle": null,
    "design_template_id": null,
    "caption_template_id": null,
    "variant_status": null,
    "design_id": null,
    "created_at": "2026-10-20T10:00:00.000Z",
    "updated_at": "2026-10-20T10:00:00.000Z"
  },
  "is_collab": false,
  "collab_handles": [],
  "collab_price_cents": 0,
  "brief": null,
  "requested_publish_at": null,
  "negotiation": {
    "offer_price_cents": null,
    "counter_price_cents": null,
    "rounds": 0
  },
  "scheduled_at": null,
  "published_at": null,
  "completed_at": null,
  "expires_at": "2026-10-30T10:00:00.000Z",
  "permalink": null,
  "auto_approved": false,
  "decision_reason": null,
  "decided_at": null,
  "failure_reason": null,
  "created_at": "2026-10-28T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z"
}
GET/v1/placements/{id}/messages

List placement messages

The conversation between creator and advertiser on a placement, oldest first. System messages record approvals and scheduling.

Scopeplacements:readMCP toollist_placement_messages
Path parameters
idrequired
stringPlacement ID
Request
curl "https://croud.ai/api/v1/placements/plc_123/messages" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0msg001",
      "object": "placement_message",
      "placement_id": "cmf0plc001",
      "side": "system",
      "author": null,
      "body": "Approved. Scheduled for 2026-11-02T15:00:00.000Z.",
      "created_at": "2026-10-28T11:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
POST/v1/placements/{id}/messages

Send a placement message

Post a message to the other side of a placement. Requires placements:write on the creator side or campaigns:write on the advertiser side.

Scopeplacements:write or campaigns:writeMCP toolsend_placement_message
Path parameters
idrequired
stringPlacement ID
Body
bodyrequired
stringMessage text, up to 2,000 characters
Request
curl -X POST "https://croud.ai/api/v1/placements/plc_123/messages" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"body":"Can we move this to Thursday?"}'
Response · 201
{
  "id": "cmf0msg002",
  "object": "placement_message",
  "placement_id": "cmf0plc001",
  "side": "creator",
  "author": "Maya Chen",
  "body": "Can we move this to Thursday?",
  "created_at": "2026-10-28T11:05:00.000Z"
}
POST/v1/placements/{id}/counter

Counter a direct request

Creator side. Answer a pending_approval direct request (origin: direct) with your own price. The placement moves to pending_advertiser until the advertiser accepts, declines or counters back. Counters on both sides are limited per request (negotiation.rounds); approve to accept the current offer instead.

Scopeplacements:writeMCP toolcounter_direct_request
Path parameters
idrequired
stringPlacement ID
Body
price_centsrequired
integerYour price for this post, in cents (at least the platform minimum offer)
message
stringOptional note to the advertiser
Request
curl -X POST "https://croud.ai/api/v1/placements/plc_123/counter" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"price_cents":60000,"message":"Happy to do this as a Reel at my usual rate."}'
Response · 200
{
  "id": "cmf0plc001",
  "object": "placement",
  "side": "creator",
  "status": "pending_advertiser",
  "origin": "direct",
  "price_cents": 45000,
  "platform_fee_cents": 4500,
  "net_payout_cents": 40500,
  "currency": "USD",
  "campaign": {
    "id": "cmf0cmp001",
    "name": "Autumn glow launch",
    "type": "targeted",
    "objective": "launch",
    "category": "beauty",
    "advertiser": {
      "id": "cmf0ws0001",
      "name": "Lumen Skincare",
      "verified": true
    },
    "start_date": "2026-11-01T00:00:00.000Z",
    "end_date": "2026-11-30T00:00:00.000Z"
  },
  "pending_status": null,
  "account": {
    "id": "cmf0acc001",
    "object": "account",
    "platform": "instagram",
    "username": "maya.creates",
    "display_name": "Maya",
    "avatar_url": null,
    "followers": 48200,
    "engagement_rate": 4.1,
    "country": "US"
  },
  "creative": {
    "id": "cmf0crt001",
    "object": "creative",
    "name": "Serum reel",
    "campaign_id": "cmf0cmp001",
    "template_id": null,
    "persona_id": null,
    "format": "ig_reel",
    "caption": "Glow season is here. #ad",
    "hashtags": [
      "#ad",
      "#skincare"
    ],
    "cta": "Shop now",
    "link_url": "https://lumen.example/serum",
    "media": [],
    "status": "ready",
    "ai_generated": false,
    "version": 1,
    "kind": "standard",
    "parent_id": null,
    "variant_for_account_id": null,
    "angle": null,
    "design_template_id": null,
    "caption_template_id": null,
    "variant_status": null,
    "design_id": null,
    "created_at": "2026-10-20T10:00:00.000Z",
    "updated_at": "2026-10-20T10:00:00.000Z"
  },
  "is_collab": false,
  "collab_handles": [],
  "collab_price_cents": 0,
  "brief": null,
  "requested_publish_at": null,
  "negotiation": {
    "offer_price_cents": 45000,
    "counter_price_cents": 60000,
    "rounds": 1
  },
  "scheduled_at": null,
  "published_at": null,
  "completed_at": null,
  "expires_at": "2026-10-30T10:00:00.000Z",
  "permalink": null,
  "auto_approved": false,
  "decision_reason": null,
  "decided_at": null,
  "failure_reason": null,
  "created_at": "2026-10-28T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z"
}
Reference

Opportunities

Creator side of open campaigns: offers with a set price per post that your accounts can accept.

GET/v1/opportunities

List opportunities

Creator side. Live open campaigns your connected accounts can accept: the advertiser's price per post, your earning after the platform fee, requirements, creatives, remaining slots and a per-account fit (blockers are the advertiser's requirements, warnings are your own policy and rates). By default only campaigns that pass your policy are listed; set matching_only=false to see the rest.

Scopeaccounts:read or placements:readMCP toollist_opportunities
Query parameters
limit
integerPage size, 1–100 (default 25)
cursor
stringnext_cursor from the previous page
account_id
stringOnly evaluate this account
category
stringContent category key
format
stringOnly campaigns with a creative in this format
min_price_cents
integer
matching_only
boolean | "0" | "1" | "true" | "false"Only campaigns that pass your policy and rates (default true)
sort
"newest" | "price" | "ending"
Request
curl "https://croud.ai/api/v1/opportunities" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0cmp002",
      "name": "Glow Ambassadors",
      "description": "Show your morning routine with our vitamin C serum.",
      "category": "beauty",
      "objective": "awareness",
      "status": "active",
      "advertiser": {
        "id": "cmf0ws0001",
        "name": "Lumen Skincare",
        "logo_url": null,
        "verified": true,
        "website": "https://lumen.example"
      },
      "price_cents": 30000,
      "earning_cents": 27000,
      "currency": "USD",
      "acceptance_mode": "instant",
      "collab": true,
      "collab_handles": [
        "lumen.skincare"
      ],
      "start_date": null,
      "end_date": "2026-12-15T00:00:00.000Z",
      "slots_left": 12,
      "requirements": {
        "categories": [
          "beauty",
          "lifestyle"
        ],
        "countries": [
          "US",
          "GB"
        ],
        "min_followers": 10000,
        "max_followers": null,
        "min_engagement": 2
      },
      "landing_url": "https://lumen.example/serum",
      "creatives": [
        {
          "id": "cmf0crt002",
          "name": "Serum reel",
          "format_key": "ig_reel",
          "caption": "My 5-step morning routine #ad",
          "hashtags": [
            "#ad"
          ],
          "cta": "Shop now",
          "link_url": "https://lumen.example/serum",
          "media": [],
          "ai_generated": false
        }
      ],
      "accounts": [
        {
          "account_id": "cmf0acc001",
          "username": "maya.creates",
          "avatar_url": null,
          "followers": 48200,
          "creative_ids": [
            "cmf0crt002"
          ],
          "blockers": [],
          "warnings": [],
          "can_accept": true,
          "placement": null
        }
      ],
      "launched_at": "2026-10-20T10:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
GET/v1/opportunities/{id}

Get an opportunity

Creator side. One open campaign with per-account fit. Campaigns that closed are still returned when one of your accounts joined them (live: false).

Scopeaccounts:read or placements:readMCP toolget_opportunity
Path parameters
idrequired
stringCampaign ID
Request
curl "https://croud.ai/api/v1/opportunities/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0cmp002",
  "name": "Glow Ambassadors",
  "description": "Show your morning routine with our vitamin C serum.",
  "category": "beauty",
  "objective": "awareness",
  "status": "active",
  "advertiser": {
    "id": "cmf0ws0001",
    "name": "Lumen Skincare",
    "logo_url": null,
    "verified": true,
    "website": "https://lumen.example"
  },
  "price_cents": 30000,
  "earning_cents": 27000,
  "currency": "USD",
  "acceptance_mode": "instant",
  "collab": true,
  "collab_handles": [
    "lumen.skincare"
  ],
  "start_date": null,
  "end_date": "2026-12-15T00:00:00.000Z",
  "slots_left": 12,
  "requirements": {
    "categories": [
      "beauty",
      "lifestyle"
    ],
    "countries": [
      "US",
      "GB"
    ],
    "min_followers": 10000,
    "max_followers": null,
    "min_engagement": 2
  },
  "landing_url": "https://lumen.example/serum",
  "creatives": [
    {
      "id": "cmf0crt002",
      "name": "Serum reel",
      "format_key": "ig_reel",
      "caption": "My 5-step morning routine #ad",
      "hashtags": [
        "#ad"
      ],
      "cta": "Shop now",
      "link_url": "https://lumen.example/serum",
      "media": [],
      "ai_generated": false
    }
  ],
  "accounts": [
    {
      "account_id": "cmf0acc001",
      "username": "maya.creates",
      "avatar_url": null,
      "followers": 48200,
      "creative_ids": [
        "cmf0crt002"
      ],
      "blockers": [],
      "warnings": [],
      "can_accept": true,
      "placement": null
    }
  ],
  "launched_at": "2026-10-20T10:00:00.000Z",
  "live": true,
  "can_act": true
}
POST/v1/opportunities/{id}/accept

Accept an opportunity

Creator side. Accept an open campaign with one of your accounts and one of the campaign's creatives. instant campaigns book the slot right away (funds move from the campaign's escrow and the post is scheduled); review campaigns create an application (pending_advertiser) the advertiser approves or declines.

Scopeplacements:writeMCP toolaccept_opportunity
Path parameters
idrequired
stringCampaign ID
Body
account_idrequired
stringYour connected account
creative_idrequired
stringOne of the campaign's creatives
message
stringOptional note to the advertiser
Request
curl -X POST "https://croud.ai/api/v1/opportunities/id_123/accept" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"account_id":"cmf0acc001","creative_id":"cmf0crt002"}'
Response · 201
{
  "object": "opportunity_acceptance",
  "placement_id": "cmf0plc009",
  "status": "scheduled",
  "scheduled_at": "2026-11-02T15:00:00.000Z",
  "placement": {
    "id": "cmf0plc009",
    "object": "placement",
    "side": "creator",
    "status": "scheduled",
    "origin": "open",
    "price_cents": 45000,
    "platform_fee_cents": 4500,
    "net_payout_cents": 40500,
    "currency": "USD",
    "campaign": {
      "id": "cmf0cmp001",
      "name": "Autumn glow launch",
      "type": "targeted",
      "objective": "launch",
      "category": "beauty",
      "advertiser": {
        "id": "cmf0ws0001",
        "name": "Lumen Skincare",
        "verified": true
      },
      "start_date": "2026-11-01T00:00:00.000Z",
      "end_date": "2026-11-30T00:00:00.000Z"
    },
    "pending_status": null,
    "account": {
      "id": "cmf0acc001",
      "object": "account",
      "platform": "instagram",
      "username": "maya.creates",
      "display_name": "Maya",
      "avatar_url": null,
      "followers": 48200,
      "engagement_rate": 4.1,
      "country": "US"
    },
    "creative": {
      "id": "cmf0crt001",
      "object": "creative",
      "name": "Serum reel",
      "campaign_id": "cmf0cmp001",
      "template_id": null,
      "persona_id": null,
      "format": "ig_reel",
      "caption": "Glow season is here. #ad",
      "hashtags": [
        "#ad",
        "#skincare"
      ],
      "cta": "Shop now",
      "link_url": "https://lumen.example/serum",
      "media": [],
      "status": "ready",
      "ai_generated": false,
      "version": 1,
      "kind": "standard",
      "parent_id": null,
      "variant_for_account_id": null,
      "angle": null,
      "design_template_id": null,
      "caption_template_id": null,
      "variant_status": null,
      "design_id": null,
      "created_at": "2026-10-20T10:00:00.000Z",
      "updated_at": "2026-10-20T10:00:00.000Z"
    },
    "is_collab": true,
    "collab_handles": [
      "lumen.skincare"
    ],
    "collab_price_cents": 0,
    "brief": null,
    "requested_publish_at": null,
    "negotiation": {
      "offer_price_cents": null,
      "counter_price_cents": null,
      "rounds": 0
    },
    "scheduled_at": null,
    "published_at": null,
    "completed_at": null,
    "expires_at": "2026-10-30T10:00:00.000Z",
    "permalink": null,
    "auto_approved": false,
    "decision_reason": null,
    "decided_at": null,
    "failure_reason": null,
    "created_at": "2026-10-28T10:00:00.000Z",
    "updated_at": "2026-10-28T10:00:00.000Z"
  }
}
Reference

Requests

Advertiser side of direct requests and open-campaign applications: send, negotiate and review.

GET/v1/requests/preview

Preview a direct request

Advertiser side. Before sending a request: whether the creator takes direct requests (mode), their public rates (with collab add-ons), what they'd ask for this creative (asking_cents) and public-safe warnings for your campaign, creative and price. Nothing is sent.

Scopemarketplace:readMCP toolpreview_direct_request
Query parameters
account_idrequired
stringCreator account ID from the marketplace
campaign_id
string
creative_id
string
price_cents
integerYour offer; defaults to the creator's rate
collab
boolean | "0" | "1" | "true" | "false"Request a collab post
Request
curl "https://croud.ai/api/v1/requests/preview?account_id=string" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "account": {
    "id": "cmf0acc003",
    "username": "techbyleo",
    "display_name": "Leo",
    "avatar_url": null,
    "followers": 182000
  },
  "mode": "anyone",
  "rates": [
    {
      "format_key": "ig_reel",
      "price_cents": 90000,
      "collab_enabled": true,
      "collab_price_cents": 18000
    }
  ],
  "approval_sla_hours": 48,
  "can_send": true,
  "warnings": [
    "Below their rate for this format"
  ],
  "asking_cents": 108000
}
GET/v1/requests/campaigns

List requestable campaigns

Advertiser side. Running targeted and direct campaigns a request can be attached to, with their ready creatives and remaining budget (budget minus committed and pending requests).

Scopecampaigns:readMCP toollist_requestable_campaigns
Request
curl "https://croud.ai/api/v1/requests/campaigns" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0cmp003",
      "name": "Creator Spotlights",
      "type": "direct",
      "status": "active",
      "collab": false,
      "collab_handles": [],
      "remaining_cents": 250000,
      "creatives": [
        {
          "id": "cmf0crt003",
          "name": "Spotlight reel",
          "format_key": "ig_reel",
          "thumbnail": null
        }
      ]
    }
  ],
  "has_more": false,
  "next_cursor": null
}
POST/v1/requests

Send a direct request

Advertiser side. Send a hand-picked creator a request for one creative of a running targeted or direct campaign, at your price. The price is reserved from your wallet; the creator approves, declines or counters (placement.countered webhook). Requires direct requests on your plan (and collab posts for collab: true).

Scopecampaigns:writeMCP toolsend_direct_request
Body
account_idrequired
stringCreator account ID
campaign_idrequired
string
creative_idrequired
stringA ready creative of the campaign
price_centsrequired
integerYour offer for the post (at least the platform minimum)
collab
booleanAsk for a collab post with your brand as collaborator
brief
stringNote to the creator
requested_publish_at
stringPreferred publish time (ISO 8601)
Request
curl -X POST "https://croud.ai/api/v1/requests" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"account_id":"cmf0acc003","campaign_id":"cmf0cmp003","creative_id":"cmf0crt003","price_cents":90000,"brief":"Unboxing in your usual style.","requested_publish_at":"2026-11-05T17:00:00Z"}'
Response · 201
{
  "id": "cmf0plc001",
  "object": "placement",
  "side": "advertiser",
  "status": "pending_approval",
  "origin": "direct",
  "price_cents": 45000,
  "platform_fee_cents": 4500,
  "net_payout_cents": 40500,
  "currency": "USD",
  "campaign": {
    "id": "cmf0cmp001",
    "name": "Autumn glow launch",
    "type": "targeted",
    "objective": "launch",
    "category": "beauty",
    "advertiser": {
      "id": "cmf0ws0001",
      "name": "Lumen Skincare",
      "verified": true
    },
    "start_date": "2026-11-01T00:00:00.000Z",
    "end_date": "2026-11-30T00:00:00.000Z"
  },
  "pending_status": null,
  "account": {
    "id": "cmf0acc001",
    "object": "account",
    "platform": "instagram",
    "username": "maya.creates",
    "display_name": "Maya",
    "avatar_url": null,
    "followers": 48200,
    "engagement_rate": 4.1,
    "country": "US"
  },
  "creative": {
    "id": "cmf0crt001",
    "object": "creative",
    "name": "Serum reel",
    "campaign_id": "cmf0cmp001",
    "template_id": null,
    "persona_id": null,
    "format": "ig_reel",
    "caption": "Glow season is here. #ad",
    "hashtags": [
      "#ad",
      "#skincare"
    ],
    "cta": "Shop now",
    "link_url": "https://lumen.example/serum",
    "media": [],
    "status": "ready",
    "ai_generated": false,
    "version": 1,
    "kind": "standard",
    "parent_id": null,
    "variant_for_account_id": null,
    "angle": null,
    "design_template_id": null,
    "caption_template_id": null,
    "variant_status": null,
    "design_id": null,
    "created_at": "2026-10-20T10:00:00.000Z",
    "updated_at": "2026-10-20T10:00:00.000Z"
  },
  "is_collab": false,
  "collab_handles": [],
  "collab_price_cents": 0,
  "brief": "Show the serum in your morning routine; mention the 20% launch code.",
  "requested_publish_at": "2026-11-05T17:00:00.000Z",
  "negotiation": {
    "offer_price_cents": 45000,
    "counter_price_cents": null,
    "rounds": 0
  },
  "scheduled_at": null,
  "published_at": null,
  "completed_at": null,
  "expires_at": "2026-10-30T10:00:00.000Z",
  "permalink": null,
  "auto_approved": false,
  "decision_reason": null,
  "decided_at": null,
  "failure_reason": null,
  "created_at": "2026-10-28T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z"
}
GET/v1/requests

List sent requests

Advertiser side. Direct requests you sent and applications to your open campaigns, newest first. status groups: action (a counter-offer or application waiting on you), waiting (on the creator), booked, closed.

Scopecampaigns:readMCP toollist_sent_requests
Query parameters
limit
integerPage size, 1–100 (default 25)
cursor
stringnext_cursor from the previous page
status
"action" | "waiting" | "booked" | "closed"action | waiting | booked | closed
origin
"direct" | "open"direct requests or open-campaign applications
campaign_id
string
Request
curl "https://croud.ai/api/v1/requests" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0plc001",
      "object": "placement",
      "side": "advertiser",
      "status": "pending_advertiser",
      "origin": "direct",
      "price_cents": 45000,
      "platform_fee_cents": 4500,
      "net_payout_cents": 40500,
      "currency": "USD",
      "campaign": {
        "id": "cmf0cmp001",
        "name": "Autumn glow launch",
        "type": "targeted",
        "objective": "launch",
        "category": "beauty",
        "advertiser": {
          "id": "cmf0ws0001",
          "name": "Lumen Skincare",
          "verified": true
        },
        "start_date": "2026-11-01T00:00:00.000Z",
        "end_date": "2026-11-30T00:00:00.000Z"
      },
      "pending_status": null,
      "account": {
        "id": "cmf0acc001",
        "object": "account",
        "platform": "instagram",
        "username": "maya.creates",
        "display_name": "Maya",
        "avatar_url": null,
        "followers": 48200,
        "engagement_rate": 4.1,
        "country": "US"
      },
      "creative": {
        "id": "cmf0crt001",
        "object": "creative",
        "name": "Serum reel",
        "campaign_id": "cmf0cmp001",
        "template_id": null,
        "persona_id": null,
        "format": "ig_reel",
        "caption": "Glow season is here. #ad",
        "hashtags": [
          "#ad",
          "#skincare"
        ],
        "cta": "Shop now",
        "link_url": "https://lumen.example/serum",
        "media": [],
        "status": "ready",
        "ai_generated": false,
        "version": 1,
        "kind": "standard",
        "parent_id": null,
        "variant_for_account_id": null,
        "angle": null,
        "design_template_id": null,
        "caption_template_id": null,
        "variant_status": null,
        "design_id": null,
        "created_at": "2026-10-20T10:00:00.000Z",
        "updated_at": "2026-10-20T10:00:00.000Z"
      },
      "is_collab": false,
      "collab_handles": [],
      "collab_price_cents": 0,
      "brief": "Show the serum in your morning routine; mention the 20% launch code.",
      "requested_publish_at": "2026-11-05T17:00:00.000Z",
      "negotiation": {
        "offer_price_cents": 45000,
        "counter_price_cents": 60000,
        "rounds": 1
      },
      "scheduled_at": null,
      "published_at": null,
      "completed_at": null,
      "expires_at": "2026-10-30T10:00:00.000Z",
      "permalink": null,
      "auto_approved": false,
      "decision_reason": null,
      "decided_at": null,
      "failure_reason": null,
      "created_at": "2026-10-28T10:00:00.000Z",
      "updated_at": "2026-10-28T10:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
GET/v1/requests/{id}

Get a sent request

Advertiser side. One direct request or application with its negotiation state, the actions you can take now, and the message thread.

Scopecampaigns:readMCP toolget_sent_request
Path parameters
idrequired
stringPlacement ID
Request
curl "https://croud.ai/api/v1/requests/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0plc001",
  "object": "placement",
  "side": "advertiser",
  "status": "pending_advertiser",
  "origin": "direct",
  "price_cents": 45000,
  "platform_fee_cents": 4500,
  "net_payout_cents": 40500,
  "currency": "USD",
  "campaign": {
    "id": "cmf0cmp001",
    "name": "Autumn glow launch",
    "type": "targeted",
    "objective": "launch",
    "category": "beauty",
    "advertiser": {
      "id": "cmf0ws0001",
      "name": "Lumen Skincare",
      "verified": true
    },
    "start_date": "2026-11-01T00:00:00.000Z",
    "end_date": "2026-11-30T00:00:00.000Z"
  },
  "pending_status": null,
  "account": {
    "id": "cmf0acc001",
    "object": "account",
    "platform": "instagram",
    "username": "maya.creates",
    "display_name": "Maya",
    "avatar_url": null,
    "followers": 48200,
    "engagement_rate": 4.1,
    "country": "US"
  },
  "creative": {
    "id": "cmf0crt001",
    "object": "creative",
    "name": "Serum reel",
    "campaign_id": "cmf0cmp001",
    "template_id": null,
    "persona_id": null,
    "format": "ig_reel",
    "caption": "Glow season is here. #ad",
    "hashtags": [
      "#ad",
      "#skincare"
    ],
    "cta": "Shop now",
    "link_url": "https://lumen.example/serum",
    "media": [],
    "status": "ready",
    "ai_generated": false,
    "version": 1,
    "kind": "standard",
    "parent_id": null,
    "variant_for_account_id": null,
    "angle": null,
    "design_template_id": null,
    "caption_template_id": null,
    "variant_status": null,
    "design_id": null,
    "created_at": "2026-10-20T10:00:00.000Z",
    "updated_at": "2026-10-20T10:00:00.000Z"
  },
  "is_collab": false,
  "collab_handles": [],
  "collab_price_cents": 0,
  "brief": "Show the serum in your morning routine; mention the 20% launch code.",
  "requested_publish_at": "2026-11-05T17:00:00.000Z",
  "negotiation": {
    "offer_price_cents": 45000,
    "counter_price_cents": 60000,
    "rounds": 1,
    "max_rounds": 4
  },
  "scheduled_at": null,
  "published_at": null,
  "completed_at": null,
  "expires_at": "2026-10-30T10:00:00.000Z",
  "permalink": null,
  "auto_approved": false,
  "decision_reason": null,
  "decided_at": null,
  "failure_reason": null,
  "created_at": "2026-10-28T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z",
  "actions": {
    "accept_counter": true,
    "counter": true,
    "decline_counter": true,
    "approve_application": false,
    "decline_application": false,
    "withdraw": true,
    "message": true
  },
  "messages": [
    {
      "id": "cmf0msg003",
      "object": "placement_message",
      "placement_id": "cmf0plc001",
      "side": "system",
      "author": null,
      "body": "@techbyleo countered with $600.00 (offer was $450.00).",
      "created_at": "2026-10-28T12:00:00.000Z"
    }
  ]
}
POST/v1/requests/{id}/respond

Respond to a counter-offer

Advertiser side. Answer a creator's counter-offer on a direct request (pending_advertiser): accept books it at the counter price (the difference is reserved from your wallet), counter sends a new price back, decline closes the request and releases the reserve.

Scopecampaigns:writeMCP toolrespond_to_counter_offer
Path parameters
idrequired
stringPlacement ID
Body
actionrequired
"accept" | "counter" | "decline"
price_cents
integerRequired for counter
message
stringOptional note to the creator
Request
curl -X POST "https://croud.ai/api/v1/requests/id_123/respond" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action":"counter","price_cents":52000,"message":"We can meet in the middle."}'
Response · 200
{
  "id": "cmf0plc001",
  "object": "placement",
  "side": "advertiser",
  "status": "pending_approval",
  "origin": "direct",
  "price_cents": 52000,
  "platform_fee_cents": 4500,
  "net_payout_cents": 40500,
  "currency": "USD",
  "campaign": {
    "id": "cmf0cmp001",
    "name": "Autumn glow launch",
    "type": "targeted",
    "objective": "launch",
    "category": "beauty",
    "advertiser": {
      "id": "cmf0ws0001",
      "name": "Lumen Skincare",
      "verified": true
    },
    "start_date": "2026-11-01T00:00:00.000Z",
    "end_date": "2026-11-30T00:00:00.000Z"
  },
  "pending_status": null,
  "account": {
    "id": "cmf0acc001",
    "object": "account",
    "platform": "instagram",
    "username": "maya.creates",
    "display_name": "Maya",
    "avatar_url": null,
    "followers": 48200,
    "engagement_rate": 4.1,
    "country": "US"
  },
  "creative": {
    "id": "cmf0crt001",
    "object": "creative",
    "name": "Serum reel",
    "campaign_id": "cmf0cmp001",
    "template_id": null,
    "persona_id": null,
    "format": "ig_reel",
    "caption": "Glow season is here. #ad",
    "hashtags": [
      "#ad",
      "#skincare"
    ],
    "cta": "Shop now",
    "link_url": "https://lumen.example/serum",
    "media": [],
    "status": "ready",
    "ai_generated": false,
    "version": 1,
    "kind": "standard",
    "parent_id": null,
    "variant_for_account_id": null,
    "angle": null,
    "design_template_id": null,
    "caption_template_id": null,
    "variant_status": null,
    "design_id": null,
    "created_at": "2026-10-20T10:00:00.000Z",
    "updated_at": "2026-10-20T10:00:00.000Z"
  },
  "is_collab": false,
  "collab_handles": [],
  "collab_price_cents": 0,
  "brief": "Show the serum in your morning routine; mention the 20% launch code.",
  "requested_publish_at": "2026-11-05T17:00:00.000Z",
  "negotiation": {
    "offer_price_cents": 52000,
    "counter_price_cents": 60000,
    "rounds": 2
  },
  "scheduled_at": null,
  "published_at": null,
  "completed_at": null,
  "expires_at": "2026-10-30T10:00:00.000Z",
  "permalink": null,
  "auto_approved": false,
  "decision_reason": null,
  "decided_at": null,
  "failure_reason": null,
  "created_at": "2026-10-28T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z"
}
POST/v1/requests/{id}/review

Review an application

Advertiser side. Approve or decline a creator's application to a review open campaign (origin: open, pending_advertiser). Approving schedules the post; declining shares the reason with the creator.

Scopecampaigns:writeMCP toolreview_application
Path parameters
idrequired
stringPlacement ID
Body
decisionrequired
"approve" | "decline"
reason
stringShared with the creator when declining
Request
curl -X POST "https://croud.ai/api/v1/requests/id_123/review" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"decision":"approve"}'
Response · 200
{
  "id": "cmf0plc001",
  "object": "placement",
  "side": "advertiser",
  "status": "scheduled",
  "origin": "open",
  "price_cents": 45000,
  "platform_fee_cents": 4500,
  "net_payout_cents": 40500,
  "currency": "USD",
  "campaign": {
    "id": "cmf0cmp001",
    "name": "Autumn glow launch",
    "type": "targeted",
    "objective": "launch",
    "category": "beauty",
    "advertiser": {
      "id": "cmf0ws0001",
      "name": "Lumen Skincare",
      "verified": true
    },
    "start_date": "2026-11-01T00:00:00.000Z",
    "end_date": "2026-11-30T00:00:00.000Z"
  },
  "pending_status": null,
  "account": {
    "id": "cmf0acc001",
    "object": "account",
    "platform": "instagram",
    "username": "maya.creates",
    "display_name": "Maya",
    "avatar_url": null,
    "followers": 48200,
    "engagement_rate": 4.1,
    "country": "US"
  },
  "creative": {
    "id": "cmf0crt001",
    "object": "creative",
    "name": "Serum reel",
    "campaign_id": "cmf0cmp001",
    "template_id": null,
    "persona_id": null,
    "format": "ig_reel",
    "caption": "Glow season is here. #ad",
    "hashtags": [
      "#ad",
      "#skincare"
    ],
    "cta": "Shop now",
    "link_url": "https://lumen.example/serum",
    "media": [],
    "status": "ready",
    "ai_generated": false,
    "version": 1,
    "kind": "standard",
    "parent_id": null,
    "variant_for_account_id": null,
    "angle": null,
    "design_template_id": null,
    "caption_template_id": null,
    "variant_status": null,
    "design_id": null,
    "created_at": "2026-10-20T10:00:00.000Z",
    "updated_at": "2026-10-20T10:00:00.000Z"
  },
  "is_collab": false,
  "collab_handles": [],
  "collab_price_cents": 0,
  "brief": null,
  "requested_publish_at": null,
  "negotiation": {
    "offer_price_cents": null,
    "counter_price_cents": null,
    "rounds": 0
  },
  "scheduled_at": "2026-11-02T15:00:00.000Z",
  "published_at": null,
  "completed_at": null,
  "expires_at": "2026-10-30T10:00:00.000Z",
  "permalink": null,
  "auto_approved": false,
  "decision_reason": null,
  "decided_at": null,
  "failure_reason": null,
  "created_at": "2026-10-28T10:00:00.000Z",
  "updated_at": "2026-10-28T10:00:00.000Z"
}
Reference

Accounts

Connected creator accounts, their ad policy, requirements and rate cards.

GET/v1/accounts

List connected accounts

Instagram accounts connected to this workspace (creator side), largest first, with approval mode and pending request counts.

Scopeaccounts:readMCP toollist_accounts
Query parameters
limit
integerPage size, 1–100 (default 25)
cursor
stringnext_cursor from the previous page
status
"connected" | "expired" | "error" | "disconnected"
purpose
"monetize" | "brand"monetize = hosts ads; brand = advertiser's own account
team_id
string
q
stringMatch on username or display name
Request
curl "https://croud.ai/api/v1/accounts" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0acc001",
      "object": "account",
      "platform": "instagram",
      "username": "maya.creates",
      "display_name": "Maya",
      "avatar_url": null,
      "followers": 48200,
      "engagement_rate": 4.1,
      "country": "US",
      "bio": "Skincare & slow mornings",
      "account_type": "creator",
      "purpose": "monetize",
      "following": 512,
      "media_count": 840,
      "avg_reach": 21000,
      "categories": [
        "beauty",
        "lifestyle"
      ],
      "audience": {
        "countries": {
          "US": 0.62
        },
        "age_ranges": {
          "25-34": 0.41
        },
        "gender": {
          "female": 0.78
        }
      },
      "language": "en",
      "status": "connected",
      "status_message": null,
      "is_listed": true,
      "description": "Skincare routines and slow-morning rituals for women in their late twenties.",
      "categories_source": "auto",
      "analysis_status": "ready",
      "analyzed_at": "2026-10-28T06:00:00.000Z",
      "team_id": null,
      "last_synced_at": "2026-10-28T06:00:00.000Z",
      "created_at": "2026-09-01T10:00:00.000Z",
      "approval_mode": "manual",
      "accepting_campaigns": true,
      "pending_requests": 2
    }
  ],
  "has_more": false,
  "next_cursor": null
}
GET/v1/accounts/{id}

Get an account

One connected account with its ad policy and rate cards.

Scopeaccounts:readMCP toolget_account
Path parameters
idrequired
stringAccount ID
Request
curl "https://croud.ai/api/v1/accounts/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0acc001",
  "object": "account",
  "platform": "instagram",
  "username": "maya.creates",
  "display_name": "Maya",
  "avatar_url": null,
  "followers": 48200,
  "engagement_rate": 4.1,
  "country": "US",
  "bio": "Skincare & slow mornings",
  "account_type": "creator",
  "purpose": "monetize",
  "following": 512,
  "media_count": 840,
  "avg_reach": 21000,
  "categories": [
    "beauty",
    "lifestyle"
  ],
  "audience": {
    "countries": {
      "US": 0.62
    },
    "age_ranges": {
      "25-34": 0.41
    },
    "gender": {
      "female": 0.78
    }
  },
  "language": "en",
  "status": "connected",
  "status_message": null,
  "is_listed": true,
  "description": "Skincare routines and slow-morning rituals for women in their late twenties.",
  "categories_source": "auto",
  "analysis_status": "ready",
  "analyzed_at": "2026-10-28T06:00:00.000Z",
  "team_id": null,
  "last_synced_at": "2026-10-28T06:00:00.000Z",
  "created_at": "2026-09-01T10:00:00.000Z",
  "team": null,
  "policy": {
    "object": "ad_policy",
    "account_id": "cmf0acc001",
    "accepting_campaigns": true,
    "approval_mode": "manual",
    "auto_approve_rules": null,
    "allowed_categories": [],
    "blocked_categories": [
      "gambling",
      "politics"
    ],
    "blocked_keywords": [],
    "blocked_advertiser_ids": [],
    "allowed_formats": [],
    "require_disclosure": true,
    "disclosure_text": "#ad",
    "allow_ai_generated": true,
    "allow_caption_edits": true,
    "min_budget_cents": 0,
    "min_price_cents": 15000,
    "min_lead_time_hours": 24,
    "min_campaign_days": 1,
    "min_advertiser_age_days": 0,
    "require_verified_advertiser": false,
    "max_ads_per_day": 1,
    "max_ads_per_week": 3,
    "min_hours_between_ads": 12,
    "posting_windows": [
      {
        "day": 1,
        "start": "09:00",
        "end": "21:00"
      }
    ],
    "approval_sla_hours": 48,
    "direct_requests": "anyone",
    "content_guidelines": null,
    "updated_at": "2026-10-28T10:00:00.000Z"
  },
  "rate_cards": [
    {
      "id": "cmf0rc0001",
      "object": "rate_card",
      "account_id": "cmf0acc001",
      "format": "ig_reel",
      "price_cents": 45000,
      "currency": "USD",
      "pricing_mode": "auto",
      "suggested_price_cents": 45000,
      "collab_enabled": true,
      "collab_price_cents": 9000,
      "collab_pricing_mode": "auto",
      "suggested_collab_cents": 9000,
      "min_duration_hours": 72,
      "active": true,
      "updated_at": "2026-10-28T10:00:00.000Z"
    }
  ]
}
PATCH/v1/accounts/{id}

Update account settings

Marketplace listing, purpose and team assignment.

Scopeaccounts:writeMCP toolupdate_account_settings
Path parameters
idrequired
stringAccount ID
Body
is_listed
booleanVisible in the advertiser marketplace
purpose
"monetize" | "brand"
team_id
string | null
Request
curl -X PATCH "https://croud.ai/api/v1/accounts/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"is_listed":false}'
Response · 200
{
  "id": "cmf0acc001",
  "object": "account",
  "platform": "instagram",
  "username": "maya.creates",
  "display_name": "Maya",
  "avatar_url": null,
  "followers": 48200,
  "engagement_rate": 4.1,
  "country": "US",
  "bio": "Skincare & slow mornings",
  "account_type": "creator",
  "purpose": "monetize",
  "following": 512,
  "media_count": 840,
  "avg_reach": 21000,
  "categories": [
    "beauty",
    "lifestyle"
  ],
  "audience": {
    "countries": {
      "US": 0.62
    },
    "age_ranges": {
      "25-34": 0.41
    },
    "gender": {
      "female": 0.78
    }
  },
  "language": "en",
  "status": "connected",
  "status_message": null,
  "is_listed": false,
  "description": "Skincare routines and slow-morning rituals for women in their late twenties.",
  "categories_source": "auto",
  "analysis_status": "ready",
  "analyzed_at": "2026-10-28T06:00:00.000Z",
  "team_id": null,
  "last_synced_at": "2026-10-28T06:00:00.000Z",
  "created_at": "2026-09-01T10:00:00.000Z",
  "team": null,
  "policy": {
    "object": "ad_policy",
    "account_id": "cmf0acc001",
    "accepting_campaigns": true,
    "approval_mode": "manual",
    "auto_approve_rules": null,
    "allowed_categories": [],
    "blocked_categories": [
      "gambling",
      "politics"
    ],
    "blocked_keywords": [],
    "blocked_advertiser_ids": [],
    "allowed_formats": [],
    "require_disclosure": true,
    "disclosure_text": "#ad",
    "allow_ai_generated": true,
    "allow_caption_edits": true,
    "min_budget_cents": 0,
    "min_price_cents": 15000,
    "min_lead_time_hours": 24,
    "min_campaign_days": 1,
    "min_advertiser_age_days": 0,
    "require_verified_advertiser": false,
    "max_ads_per_day": 1,
    "max_ads_per_week": 3,
    "min_hours_between_ads": 12,
    "posting_windows": [
      {
        "day": 1,
        "start": "09:00",
        "end": "21:00"
      }
    ],
    "approval_sla_hours": 48,
    "direct_requests": "anyone",
    "content_guidelines": null,
    "updated_at": "2026-10-28T10:00:00.000Z"
  },
  "rate_cards": [
    {
      "id": "cmf0rc0001",
      "object": "rate_card",
      "account_id": "cmf0acc001",
      "format": "ig_reel",
      "price_cents": 45000,
      "currency": "USD",
      "pricing_mode": "auto",
      "suggested_price_cents": 45000,
      "collab_enabled": true,
      "collab_price_cents": 9000,
      "collab_pricing_mode": "auto",
      "suggested_collab_cents": 9000,
      "min_duration_hours": 72,
      "active": true,
      "updated_at": "2026-10-28T10:00:00.000Z"
    }
  ]
}
GET/v1/accounts/{id}/policy

Get the ad policy

Content rules, minimum requirements, pacing, posting windows and approval settings that every ad request is checked against. null until the policy is first saved.

Scopeaccounts:readMCP toolget_account_policy
Path parameters
idrequired
stringAccount ID
Request
curl "https://croud.ai/api/v1/accounts/id_123/policy" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "ad_policy",
  "account_id": "cmf0acc001",
  "accepting_campaigns": true,
  "approval_mode": "manual",
  "auto_approve_rules": null,
  "allowed_categories": [],
  "blocked_categories": [
    "gambling",
    "politics"
  ],
  "blocked_keywords": [],
  "blocked_advertiser_ids": [],
  "allowed_formats": [],
  "require_disclosure": true,
  "disclosure_text": "#ad",
  "allow_ai_generated": true,
  "allow_caption_edits": true,
  "min_budget_cents": 0,
  "min_price_cents": 15000,
  "min_lead_time_hours": 24,
  "min_campaign_days": 1,
  "min_advertiser_age_days": 0,
  "require_verified_advertiser": false,
  "max_ads_per_day": 1,
  "max_ads_per_week": 3,
  "min_hours_between_ads": 12,
  "posting_windows": [
    {
      "day": 1,
      "start": "09:00",
      "end": "21:00"
    }
  ],
  "approval_sla_hours": 48,
  "direct_requests": "anyone",
  "content_guidelines": null,
  "updated_at": "2026-10-28T10:00:00.000Z"
}
PATCH/v1/accounts/{id}/policy

Update content policy

Which ads the account accepts: categories, keywords, advertisers, formats, disclosure and AI content. Omitted fields keep their current values.

Scopeaccounts:writeMCP toolupdate_account_policy
Path parameters
idrequired
stringAccount ID
Body
accepting_campaigns
booleanPause all new ad requests when false
allowed_categories
string[]Empty = every category not blocked
blocked_categories
string[]
blocked_keywords
string[]Requests whose copy contains these are declined
blocked_advertiser_ids
string[]Advertiser workspace IDs
allowed_formats
string[]Empty = every enabled format
require_disclosure
boolean
disclosure_text
stringe.g. #ad
allow_ai_generated
boolean
allow_caption_edits
boolean
content_guidelines
string | null
Request
curl -X PATCH "https://croud.ai/api/v1/accounts/id_123/policy" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"blocked_categories":["gambling","politics","crypto"],"blocked_keywords":["diet pill"]}'
Response · 200
{
  "object": "ad_policy",
  "account_id": "cmf0acc001",
  "accepting_campaigns": true,
  "approval_mode": "manual",
  "auto_approve_rules": null,
  "allowed_categories": [],
  "blocked_categories": [
    "gambling",
    "politics"
  ],
  "blocked_keywords": [],
  "blocked_advertiser_ids": [],
  "allowed_formats": [],
  "require_disclosure": true,
  "disclosure_text": "#ad",
  "allow_ai_generated": true,
  "allow_caption_edits": true,
  "min_budget_cents": 0,
  "min_price_cents": 15000,
  "min_lead_time_hours": 24,
  "min_campaign_days": 1,
  "min_advertiser_age_days": 0,
  "require_verified_advertiser": false,
  "max_ads_per_day": 1,
  "max_ads_per_week": 3,
  "min_hours_between_ads": 12,
  "posting_windows": [
    {
      "day": 1,
      "start": "09:00",
      "end": "21:00"
    }
  ],
  "approval_sla_hours": 48,
  "direct_requests": "anyone",
  "content_guidelines": null,
  "updated_at": "2026-10-28T10:00:00.000Z"
}
PATCH/v1/accounts/{id}/requirements

Update requirements & pacing

Minimum price and budget, lead time, advertiser checks, ad frequency caps, approval SLA and posting windows. Omitted fields keep their current values.

Scopeaccounts:writeMCP toolupdate_account_requirements
Path parameters
idrequired
stringAccount ID
Body
min_price_cents
integer
min_budget_cents
integer
min_lead_time_hours
integer
min_campaign_days
integer
min_advertiser_age_days
integer
require_verified_advertiser
boolean
max_ads_per_day
integer
max_ads_per_week
integer
min_hours_between_ads
integer
approval_sla_hours
integerRequests expire if not decided in time
posting_windows
object[]When ads may publish; empty = any time
Request
curl -X PATCH "https://croud.ai/api/v1/accounts/id_123/requirements" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"min_price_cents":20000,"max_ads_per_week":2,"posting_windows":[{"day":2,"start":"17:00","end":"21:00"}]}'
Response · 200
{
  "object": "ad_policy",
  "account_id": "cmf0acc001",
  "accepting_campaigns": true,
  "approval_mode": "manual",
  "auto_approve_rules": null,
  "allowed_categories": [],
  "blocked_categories": [
    "gambling",
    "politics"
  ],
  "blocked_keywords": [],
  "blocked_advertiser_ids": [],
  "allowed_formats": [],
  "require_disclosure": true,
  "disclosure_text": "#ad",
  "allow_ai_generated": true,
  "allow_caption_edits": true,
  "min_budget_cents": 0,
  "min_price_cents": 15000,
  "min_lead_time_hours": 24,
  "min_campaign_days": 1,
  "min_advertiser_age_days": 0,
  "require_verified_advertiser": false,
  "max_ads_per_day": 1,
  "max_ads_per_week": 3,
  "min_hours_between_ads": 12,
  "posting_windows": [
    {
      "day": 1,
      "start": "09:00",
      "end": "21:00"
    }
  ],
  "approval_sla_hours": 48,
  "direct_requests": "anyone",
  "content_guidelines": null,
  "updated_at": "2026-10-28T10:00:00.000Z"
}
PUT/v1/accounts/{id}/approval-settings

Set approval settings

How requests are approved: manual (every request waits for review), rules (auto-approve when rules match) or auto (approve everything that meets the policy). Rules replace the current rules when provided. direct_requests controls who may send hand-picked requests.

Scopeaccounts:writeMCP toolupdate_approval_settings
Path parameters
idrequired
stringAccount ID
Body
approval_moderequired
"manual" | "rules" | "auto"rules requires auto-approval rules on your plan
direct_requests
"anyone" | "eligible_only" | "off"Who may send hand-picked direct requests: anyone (you decide on each), eligible_only (must pass your policy and minimum price) or off. Omit to keep the current setting.
auto_approve_rules
object
Request
curl -X PUT "https://croud.ai/api/v1/accounts/id_123/approval-settings" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"approval_mode":"rules","auto_approve_rules":{"min_price_cents":30000,"categories":["beauty"],"verified_advertisers_only":true},"direct_requests":"eligible_only"}'
Response · 200
{
  "object": "ad_policy",
  "account_id": "cmf0acc001",
  "accepting_campaigns": true,
  "approval_mode": "rules",
  "auto_approve_rules": {
    "min_price_cents": 30000,
    "categories": [
      "beauty"
    ],
    "verified_advertisers_only": true,
    "trusted_workspace_ids": [],
    "require_no_ai_content": false,
    "max_placements_per_campaign": null
  },
  "allowed_categories": [],
  "blocked_categories": [
    "gambling",
    "politics"
  ],
  "blocked_keywords": [],
  "blocked_advertiser_ids": [],
  "allowed_formats": [],
  "require_disclosure": true,
  "disclosure_text": "#ad",
  "allow_ai_generated": true,
  "allow_caption_edits": true,
  "min_budget_cents": 0,
  "min_price_cents": 15000,
  "min_lead_time_hours": 24,
  "min_campaign_days": 1,
  "min_advertiser_age_days": 0,
  "require_verified_advertiser": false,
  "max_ads_per_day": 1,
  "max_ads_per_week": 3,
  "min_hours_between_ads": 12,
  "posting_windows": [
    {
      "day": 1,
      "start": "09:00",
      "end": "21:00"
    }
  ],
  "approval_sla_hours": 48,
  "direct_requests": "anyone",
  "content_guidelines": null,
  "updated_at": "2026-10-28T10:00:00.000Z"
}
GET/v1/accounts/{id}/rate-cards

List rate cards

Price per post for each format on this account.

Scopeaccounts:readMCP toollist_rate_cards
Path parameters
idrequired
stringAccount ID
Request
curl "https://croud.ai/api/v1/accounts/id_123/rate-cards" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0rc0001",
      "object": "rate_card",
      "account_id": "cmf0acc001",
      "format": "ig_reel",
      "price_cents": 45000,
      "currency": "USD",
      "pricing_mode": "auto",
      "suggested_price_cents": 45000,
      "collab_enabled": true,
      "collab_price_cents": 9000,
      "collab_pricing_mode": "auto",
      "suggested_collab_cents": 9000,
      "min_duration_hours": 72,
      "active": true,
      "updated_at": "2026-10-28T10:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
PUT/v1/accounts/{id}/rate-cards

Set rate cards

Create or update prices per format. pricing_mode: auto follows the suggested price from account analysis (and moves when the account or the pricing model changes); manual keeps your price. Enable collab posts per format with an automatic or manual add-on. Formats not included are left unchanged; set active: false to stop offering one.

Scopeaccounts:writeMCP toolupdate_rate_cards
Path parameters
idrequired
stringAccount ID
Body
rate_cardsrequired
object[]Upserted by format; formats not listed are left unchanged. Omitted fields keep their current values.
Request
curl -X PUT "https://croud.ai/api/v1/accounts/id_123/rate-cards" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"rate_cards":[{"format":"ig_reel","pricing_mode":"auto","collab_enabled":true,"collab_pricing_mode":"auto"},{"format":"ig_story","pricing_mode":"manual","price_cents":12000,"min_duration_hours":24}]}'
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0rc0001",
      "object": "rate_card",
      "account_id": "cmf0acc001",
      "format": "ig_reel",
      "price_cents": 45000,
      "currency": "USD",
      "pricing_mode": "auto",
      "suggested_price_cents": 45000,
      "collab_enabled": true,
      "collab_price_cents": 9000,
      "collab_pricing_mode": "auto",
      "suggested_collab_cents": 9000,
      "min_duration_hours": 72,
      "active": true,
      "updated_at": "2026-10-28T10:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
GET/v1/accounts/{id}/insights

Get account insights

What account analysis found: content categories (effective and suggested, with auto/manual source), the advertiser-facing description, content stats from recent posts, analysis status, and suggested prices per format with the full pricing breakdown.

Scopeaccounts:readMCP toolget_account_insights
Path parameters
idrequired
stringAccount ID
Request
curl "https://croud.ai/api/v1/accounts/id_123/insights" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "account_insights",
  "account_id": "cmf0acc001",
  "categories": [
    "beauty",
    "lifestyle"
  ],
  "categories_source": "auto",
  "suggested_categories": [
    {
      "key": "beauty",
      "confidence": 0.82
    },
    {
      "key": "lifestyle",
      "confidence": 0.41
    }
  ],
  "description": "Skincare routines and slow-morning rituals for women in their late twenties.",
  "description_source": "auto",
  "suggested_description": "Skincare routines and slow-morning rituals for women in their late twenties.",
  "analysis": {
    "status": "ready",
    "error": null,
    "model": "claude-opus-5-5",
    "analyzed_at": "2026-10-28T06:00:00.000Z"
  },
  "stats": {
    "posts_analyzed": 15,
    "period_days": 34,
    "posts_per_week": 3.1,
    "last_post_at": "2026-10-26T08:00:00.000Z",
    "format_mix": {
      "image": 4,
      "carousel": 3,
      "reel": 8
    },
    "avg_likes": 1840,
    "avg_comments": 96,
    "engagement_rate": 4,
    "medians": {
      "feed": {
        "median": 14200,
        "samples": 7
      },
      "reel": {
        "median": 21800,
        "samples": 8
      }
    },
    "reach_rate": 0.36,
    "top_hashtags": [
      "#skincare",
      "#morningroutine"
    ]
  },
  "recent_posts": [
    {
      "id": "cmf0med001",
      "media_type": "video",
      "product_type": "reels",
      "caption": "Morning routine, 5 steps",
      "permalink": "https://instagram.com/p/abc",
      "thumbnail_url": null,
      "posted_at": "2026-10-26T08:00:00.000Z",
      "likes": 2210,
      "comments": 104,
      "reach": 23100,
      "views": 31800,
      "saves": 310,
      "shares": 42
    }
  ],
  "pricing": [
    {
      "format": "ig_reel",
      "format_name": "Reel",
      "price_cents": 45000,
      "pricing_mode": "auto",
      "suggested_price_cents": 45000,
      "collab_enabled": true,
      "collab_price_cents": 9000,
      "collab_pricing_mode": "auto",
      "suggested_collab_cents": 9000,
      "breakdown": {
        "format": "reel",
        "expected_impressions": 19800,
        "impressions_source": "blended",
        "samples": 6,
        "cpm_cents": 2500,
        "factors": {
          "size": 1.02,
          "engagement": 1.21,
          "niche": 1.1,
          "geo": 0.92,
          "activity": 1.05
        },
        "raw_cents": 44310,
        "price_cents": 45000,
        "floor_applied": false,
        "collab_percent": 20,
        "collab_cents": 9000,
        "model_version": 1
      }
    }
  ]
}
PATCH/v1/accounts/{id}/profile

Update categories & description

Override the categories or description found by analysis. Edited values become manual and are kept on re-analysis; reset_categories / reset_description go back to the analysis results. Category changes reprice auto-priced rate cards.

Scopeaccounts:writeMCP toolupdate_account_profile
Path parameters
idrequired
stringAccount ID
Body
categories
string[]Content category keys (see GET /v1/reference/content_category). Marks categories as manual: re-analysis won't overwrite them.
description
stringShort summary shown to advertisers. Marks the description as manual.
reset_categories
booleanGo back to the categories found by analysis
reset_description
booleanGo back to the description written by analysis
Request
curl -X PATCH "https://croud.ai/api/v1/accounts/id_123/profile" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"categories":["beauty","wellness"],"reset_description":true}'
Response · 200
{
  "object": "account_insights",
  "account_id": "cmf0acc001",
  "categories": [
    "beauty",
    "wellness"
  ],
  "categories_source": "manual",
  "suggested_categories": [
    {
      "key": "beauty",
      "confidence": 0.82
    },
    {
      "key": "lifestyle",
      "confidence": 0.41
    }
  ],
  "description": "Skincare routines and slow-morning rituals for women in their late twenties.",
  "description_source": "auto",
  "suggested_description": "Skincare routines and slow-morning rituals for women in their late twenties.",
  "analysis": {
    "status": "ready",
    "error": null,
    "model": "claude-opus-5-5",
    "analyzed_at": "2026-10-28T06:00:00.000Z"
  },
  "stats": {
    "posts_analyzed": 15,
    "period_days": 34,
    "posts_per_week": 3.1,
    "last_post_at": "2026-10-26T08:00:00.000Z",
    "format_mix": {
      "image": 4,
      "carousel": 3,
      "reel": 8
    },
    "avg_likes": 1840,
    "avg_comments": 96,
    "engagement_rate": 4,
    "medians": {
      "feed": {
        "median": 14200,
        "samples": 7
      },
      "reel": {
        "median": 21800,
        "samples": 8
      }
    },
    "reach_rate": 0.36,
    "top_hashtags": [
      "#skincare",
      "#morningroutine"
    ]
  },
  "recent_posts": [
    {
      "id": "cmf0med001",
      "media_type": "video",
      "product_type": "reels",
      "caption": "Morning routine, 5 steps",
      "permalink": "https://instagram.com/p/abc",
      "thumbnail_url": null,
      "posted_at": "2026-10-26T08:00:00.000Z",
      "likes": 2210,
      "comments": 104,
      "reach": 23100,
      "views": 31800,
      "saves": 310,
      "shares": 42
    }
  ],
  "pricing": [
    {
      "format": "ig_reel",
      "format_name": "Reel",
      "price_cents": 45000,
      "pricing_mode": "auto",
      "suggested_price_cents": 45000,
      "collab_enabled": true,
      "collab_price_cents": 9000,
      "collab_pricing_mode": "auto",
      "suggested_collab_cents": 9000,
      "breakdown": {
        "format": "reel",
        "expected_impressions": 19800,
        "impressions_source": "blended",
        "samples": 6,
        "cpm_cents": 2500,
        "factors": {
          "size": 1.02,
          "engagement": 1.21,
          "niche": 1.1,
          "geo": 0.92,
          "activity": 1.05
        },
        "raw_cents": 44310,
        "price_cents": 45000,
        "floor_applied": false,
        "collab_percent": 20,
        "collab_cents": 9000,
        "model_version": 1
      }
    }
  ]
}
POST/v1/accounts/{id}/analyze

Re-analyze an account

Queue a fresh analysis of the account's recent posts (categories, description, stats and suggested prices). Runs in the background; poll /insights or subscribe to the account.analyzed webhook. Limited to 3 requests per account per hour.

Scopeaccounts:writeMCP toolanalyze_account
Path parameters
idrequired
stringAccount ID
Request
curl -X POST "https://croud.ai/api/v1/accounts/id_123/analyze" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 202
{
  "object": "account_analysis",
  "account_id": "cmf0acc001",
  "queued": true,
  "status": "pending"
}
POST/v1/accounts/{id}/sync

Sync an account

Refresh the account's profile, followers and engagement from Instagram now (accounts also sync daily). Auto-priced rate cards follow the new numbers.

Scopeconnections:writeMCP toolsync_account
Path parameters
idrequired
stringAccount ID
Request
curl -X POST "https://croud.ai/api/v1/accounts/id_123/sync" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0acc001",
  "object": "account",
  "platform": "instagram",
  "username": "maya.creates",
  "display_name": "Maya",
  "avatar_url": null,
  "followers": 48200,
  "engagement_rate": 4.1,
  "country": "US",
  "bio": "Skincare & slow mornings",
  "account_type": "creator",
  "purpose": "monetize",
  "following": 512,
  "media_count": 840,
  "avg_reach": 21000,
  "categories": [
    "beauty",
    "lifestyle"
  ],
  "audience": {
    "countries": {
      "US": 0.62
    },
    "age_ranges": {
      "25-34": 0.41
    },
    "gender": {
      "female": 0.78
    }
  },
  "language": "en",
  "status": "connected",
  "status_message": null,
  "is_listed": true,
  "description": "Skincare routines and slow-morning rituals for women in their late twenties.",
  "categories_source": "auto",
  "analysis_status": "ready",
  "analyzed_at": "2026-10-28T06:00:00.000Z",
  "team_id": null,
  "last_synced_at": "2026-10-28T06:00:00.000Z",
  "created_at": "2026-09-01T10:00:00.000Z",
  "team": null,
  "policy": {
    "object": "ad_policy",
    "account_id": "cmf0acc001",
    "accepting_campaigns": true,
    "approval_mode": "manual",
    "auto_approve_rules": null,
    "allowed_categories": [],
    "blocked_categories": [
      "gambling",
      "politics"
    ],
    "blocked_keywords": [],
    "blocked_advertiser_ids": [],
    "allowed_formats": [],
    "require_disclosure": true,
    "disclosure_text": "#ad",
    "allow_ai_generated": true,
    "allow_caption_edits": true,
    "min_budget_cents": 0,
    "min_price_cents": 15000,
    "min_lead_time_hours": 24,
    "min_campaign_days": 1,
    "min_advertiser_age_days": 0,
    "require_verified_advertiser": false,
    "max_ads_per_day": 1,
    "max_ads_per_week": 3,
    "min_hours_between_ads": 12,
    "posting_windows": [
      {
        "day": 1,
        "start": "09:00",
        "end": "21:00"
      }
    ],
    "approval_sla_hours": 48,
    "direct_requests": "anyone",
    "content_guidelines": null,
    "updated_at": "2026-10-28T10:00:00.000Z"
  },
  "rate_cards": [
    {
      "id": "cmf0rc0001",
      "object": "rate_card",
      "account_id": "cmf0acc001",
      "format": "ig_reel",
      "price_cents": 45000,
      "currency": "USD",
      "pricing_mode": "auto",
      "suggested_price_cents": 45000,
      "collab_enabled": true,
      "collab_price_cents": 9000,
      "collab_pricing_mode": "auto",
      "suggested_collab_cents": 9000,
      "min_duration_hours": 72,
      "active": true,
      "updated_at": "2026-10-28T10:00:00.000Z"
    }
  ]
}
POST/v1/accounts/{id}/disconnect

Disconnect an account

Disconnects the account from Croud: its token is removed, it leaves the marketplace, and open requests on it are closed (scheduled posts are canceled and advertisers are refunded). Reconnect it from the app.

Scopeconnections:writeMCP tooldisconnect_account
Path parameters
idrequired
stringAccount ID
Request
curl -X POST "https://croud.ai/api/v1/accounts/id_123/disconnect" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0acc001",
  "object": "account",
  "platform": "instagram",
  "username": "maya.creates",
  "display_name": "Maya",
  "avatar_url": null,
  "followers": 48200,
  "engagement_rate": 4.1,
  "country": "US",
  "bio": "Skincare & slow mornings",
  "account_type": "creator",
  "purpose": "monetize",
  "following": 512,
  "media_count": 840,
  "avg_reach": 21000,
  "categories": [
    "beauty",
    "lifestyle"
  ],
  "audience": {
    "countries": {
      "US": 0.62
    },
    "age_ranges": {
      "25-34": 0.41
    },
    "gender": {
      "female": 0.78
    }
  },
  "language": "en",
  "status": "disconnected",
  "status_message": null,
  "is_listed": false,
  "description": "Skincare routines and slow-morning rituals for women in their late twenties.",
  "categories_source": "auto",
  "analysis_status": "ready",
  "analyzed_at": "2026-10-28T06:00:00.000Z",
  "team_id": null,
  "last_synced_at": "2026-10-28T06:00:00.000Z",
  "created_at": "2026-09-01T10:00:00.000Z",
  "team": null,
  "policy": {
    "object": "ad_policy",
    "account_id": "cmf0acc001",
    "accepting_campaigns": true,
    "approval_mode": "manual",
    "auto_approve_rules": null,
    "allowed_categories": [],
    "blocked_categories": [
      "gambling",
      "politics"
    ],
    "blocked_keywords": [],
    "blocked_advertiser_ids": [],
    "allowed_formats": [],
    "require_disclosure": true,
    "disclosure_text": "#ad",
    "allow_ai_generated": true,
    "allow_caption_edits": true,
    "min_budget_cents": 0,
    "min_price_cents": 15000,
    "min_lead_time_hours": 24,
    "min_campaign_days": 1,
    "min_advertiser_age_days": 0,
    "require_verified_advertiser": false,
    "max_ads_per_day": 1,
    "max_ads_per_week": 3,
    "min_hours_between_ads": 12,
    "posting_windows": [
      {
        "day": 1,
        "start": "09:00",
        "end": "21:00"
      }
    ],
    "approval_sla_hours": 48,
    "direct_requests": "anyone",
    "content_guidelines": null,
    "updated_at": "2026-10-28T10:00:00.000Z"
  },
  "rate_cards": [
    {
      "id": "cmf0rc0001",
      "object": "rate_card",
      "account_id": "cmf0acc001",
      "format": "ig_reel",
      "price_cents": 45000,
      "currency": "USD",
      "pricing_mode": "auto",
      "suggested_price_cents": 45000,
      "collab_enabled": true,
      "collab_price_cents": 9000,
      "collab_pricing_mode": "auto",
      "suggested_collab_cents": 9000,
      "min_duration_hours": 72,
      "active": true,
      "updated_at": "2026-10-28T10:00:00.000Z"
    }
  ]
}
Reference

Marketplace

Search listed creator accounts.

GET/v1/marketplace/creators/{id}

Get a creator profile

A listed creator's public profile: stats, follower history, audience, rate card, track record and a summary of the ad policy you'll be matched against.

Scopemarketplace:readMCP toolget_creator_profile
Path parameters
idrequired
stringAccount ID
Request
curl "https://croud.ai/api/v1/marketplace/creators/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0acc001",
  "username": "maya.creates",
  "display_name": "Maya",
  "avatar_url": null,
  "country": "US",
  "niches": [
    "beauty",
    "lifestyle"
  ],
  "followers": 48200,
  "engagement_rate": 4.1,
  "avg_reach": 21000,
  "from_price_cents": 12000,
  "formats": [
    "ig_story",
    "ig_reel"
  ],
  "approval_mode": "rules",
  "accepting_campaigns": true,
  "description": "Skincare routines and slow-morning rituals for women in their late twenties.",
  "offers_collab": true,
  "direct_requests": "anyone",
  "bio": "Skincare & slow mornings",
  "following": 512,
  "media_count": 840,
  "language": "en",
  "account_type": "creator",
  "growth": {
    "percent": 6.2,
    "since": "2026-05-01T00:00:00.000Z"
  },
  "audience": {
    "countries": [
      [
        "US",
        0.62
      ]
    ],
    "age_ranges": [
      [
        "25-34",
        0.41
      ]
    ],
    "gender": [
      [
        "female",
        0.78
      ]
    ]
  },
  "rate_card": [
    {
      "format_key": "ig_reel",
      "price_cents": 45000,
      "currency": "USD",
      "min_duration_hours": 72,
      "format_name": "Reel"
    }
  ],
  "track": {
    "completed": 14,
    "approval_rate": 0.82
  },
  "policy": {
    "accepting_campaigns": true,
    "approval_mode": "rules",
    "approval_sla_hours": 48,
    "min_price_cents": 12000,
    "require_disclosure": true,
    "disclosure_text": "#ad"
  },
  "fit": {
    "verified_required_but_missing": false
  }
}
Reference

Personas

Brand voices used by AI content generation.

GET/v1/personas

List personas

Voices used by AI generation: the workspace's personas (default first), then the platform voices (platform: true, admin-managed and read-only, one per content type). Any of them can be passed as persona_id to POST /v1/ai/generate.

Scopepersonas:readMCP toollist_personas
Query parameters
limit
integerPage size, 1–100 (default 25)
cursor
stringnext_cursor from the previous page
status
"active" | "archived" | "all"Filters the workspace's personas; platform voices are always active
team_id
string
include_platform
boolean | "0" | "1" | "true" | "false"Include platform voices (default true; ignored for status=archived)
Request
curl "https://croud.ai/api/v1/personas" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0prs001",
      "object": "persona",
      "name": "Lumen voice",
      "avatar_url": null,
      "tagline": "Calm, clinical, kind",
      "description": "Science-backed skincare without the jargon.",
      "tone": [
        "warm",
        "expert"
      ],
      "formality": 40,
      "emoji_usage": "light",
      "language": "en",
      "audience": "Women 25–40 who read ingredient lists",
      "values": "Honesty over hype",
      "do_list": [
        "Name the key ingredient"
      ],
      "dont_list": [
        "Promise overnight results"
      ],
      "banned_words": [
        "miracle"
      ],
      "sample_posts": [],
      "hashtag_style": "minimal",
      "cta_style": "Soft invitation",
      "is_default": true,
      "status": "active",
      "team_id": null,
      "created_at": "2026-10-01T10:00:00.000Z",
      "updated_at": "2026-10-20T10:00:00.000Z",
      "platform": false,
      "key": null,
      "content_type": null
    }
  ],
  "has_more": false,
  "next_cursor": null
}
GET/v1/personas/{id}

Get a persona

Retrieve one persona: a workspace persona or a platform voice (platform: true).

Scopepersonas:readMCP toolget_persona
Path parameters
idrequired
stringPersona ID
Request
curl "https://croud.ai/api/v1/personas/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0prs001",
  "object": "persona",
  "name": "Lumen voice",
  "avatar_url": null,
  "tagline": "Calm, clinical, kind",
  "description": "Science-backed skincare without the jargon.",
  "tone": [
    "warm",
    "expert"
  ],
  "formality": 40,
  "emoji_usage": "light",
  "language": "en",
  "audience": "Women 25–40 who read ingredient lists",
  "values": "Honesty over hype",
  "do_list": [
    "Name the key ingredient"
  ],
  "dont_list": [
    "Promise overnight results"
  ],
  "banned_words": [
    "miracle"
  ],
  "sample_posts": [],
  "hashtag_style": "minimal",
  "cta_style": "Soft invitation",
  "is_default": true,
  "status": "active",
  "team_id": null,
  "created_at": "2026-10-01T10:00:00.000Z",
  "updated_at": "2026-10-20T10:00:00.000Z",
  "platform": false,
  "key": null,
  "content_type": null
}
POST/v1/personas

Create a persona

Creates a brand voice. The first active persona becomes the default. Counts toward the plan's persona limit.

Scopepersonas:writeMCP toolcreate_persona
Body
namerequired
string
tagline
string | null
description
string | null
avatar_url
string | null
team_id
any
tone
string[]Up to 6 persona_tone keys (see GET /v1/reference/persona_tone), e.g. warm, practical
formality
integer0 = casual, 100 = formal
emoji_usage
"none" | "light" | "heavy"
language
stringLanguage code, e.g. en
audience
string | null
values
string | null
do_list
string[]Things the voice always does
dont_list
string[]Things the voice never does
banned_words
string[]
sample_posts
string[]Example captions in this voice
hashtag_style
"none" | "minimal" | "moderate" | "heavy"
cta_style
string | null
Request
curl -X POST "https://croud.ai/api/v1/personas" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Lumen voice","tone":["warm","expert"],"formality":40,"emoji_usage":"light","do_list":["Name the key ingredient"],"dont_list":["Promise overnight results"],"hashtag_style":"minimal"}'
Response · 201
{
  "id": "cmf0prs001",
  "object": "persona",
  "name": "Lumen voice",
  "avatar_url": null,
  "tagline": "Calm, clinical, kind",
  "description": "Science-backed skincare without the jargon.",
  "tone": [
    "warm",
    "expert"
  ],
  "formality": 40,
  "emoji_usage": "light",
  "language": "en",
  "audience": "Women 25–40 who read ingredient lists",
  "values": "Honesty over hype",
  "do_list": [
    "Name the key ingredient"
  ],
  "dont_list": [
    "Promise overnight results"
  ],
  "banned_words": [
    "miracle"
  ],
  "sample_posts": [],
  "hashtag_style": "minimal",
  "cta_style": "Soft invitation",
  "is_default": true,
  "status": "active",
  "team_id": null,
  "created_at": "2026-10-01T10:00:00.000Z",
  "updated_at": "2026-10-20T10:00:00.000Z",
  "platform": false,
  "key": null,
  "content_type": null
}
PATCH/v1/personas/{id}

Update a persona

Update fields; omitted fields keep their values. Platform voices are read-only (403): duplicate one to edit it.

Scopepersonas:writeMCP toolupdate_persona
Path parameters
idrequired
stringPersona ID
Body
name
string
tagline
string | null
description
string | null
avatar_url
string | null
team_id
any
tone
string[]Up to 6 persona_tone keys (see GET /v1/reference/persona_tone), e.g. warm, practical
formality
integer0 = casual, 100 = formal
emoji_usage
"none" | "light" | "heavy"
language
stringLanguage code, e.g. en
audience
string | null
values
string | null
do_list
string[]Things the voice always does
dont_list
string[]Things the voice never does
banned_words
string[]
sample_posts
string[]Example captions in this voice
hashtag_style
"none" | "minimal" | "moderate" | "heavy"
cta_style
string | null
Request
curl -X PATCH "https://croud.ai/api/v1/personas/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"formality":55,"banned_words":["miracle","flawless"]}'
Response · 200
{
  "id": "cmf0prs001",
  "object": "persona",
  "name": "Lumen voice",
  "avatar_url": null,
  "tagline": "Calm, clinical, kind",
  "description": "Science-backed skincare without the jargon.",
  "tone": [
    "warm",
    "expert"
  ],
  "formality": 40,
  "emoji_usage": "light",
  "language": "en",
  "audience": "Women 25–40 who read ingredient lists",
  "values": "Honesty over hype",
  "do_list": [
    "Name the key ingredient"
  ],
  "dont_list": [
    "Promise overnight results"
  ],
  "banned_words": [
    "miracle"
  ],
  "sample_posts": [],
  "hashtag_style": "minimal",
  "cta_style": "Soft invitation",
  "is_default": true,
  "status": "active",
  "team_id": null,
  "created_at": "2026-10-01T10:00:00.000Z",
  "updated_at": "2026-10-20T10:00:00.000Z",
  "platform": false,
  "key": null,
  "content_type": null
}
POST/v1/personas/{id}/duplicate

Duplicate a persona

Copy a workspace persona or a platform voice into the workspace as an editable persona. Counts toward the plan's persona limit.

Scopepersonas:writeMCP toolduplicate_persona
Path parameters
idrequired
stringPersona ID
Request
curl -X POST "https://croud.ai/api/v1/personas/id_123/duplicate" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 201
{
  "id": "cmf0prs001",
  "object": "persona",
  "name": "Lumen voice",
  "avatar_url": null,
  "tagline": "Calm, clinical, kind",
  "description": "Science-backed skincare without the jargon.",
  "tone": [
    "warm",
    "expert"
  ],
  "formality": 40,
  "emoji_usage": "light",
  "language": "en",
  "audience": "Women 25–40 who read ingredient lists",
  "values": "Honesty over hype",
  "do_list": [
    "Name the key ingredient"
  ],
  "dont_list": [
    "Promise overnight results"
  ],
  "banned_words": [
    "miracle"
  ],
  "sample_posts": [],
  "hashtag_style": "minimal",
  "cta_style": "Soft invitation",
  "is_default": true,
  "status": "active",
  "team_id": null,
  "created_at": "2026-10-01T10:00:00.000Z",
  "updated_at": "2026-10-20T10:00:00.000Z",
  "platform": false,
  "key": null,
  "content_type": null
}
POST/v1/personas/{id}/archive

Archive a persona

Hides a workspace persona from pickers and AI generation. If it was the default, the workspace has no default until you set one. Archived personas can be restored or deleted.

Scopepersonas:writeMCP toolarchive_persona
Path parameters
idrequired
stringPersona ID
Request
curl -X POST "https://croud.ai/api/v1/personas/id_123/archive" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0prs001",
  "object": "persona",
  "name": "Lumen voice",
  "avatar_url": null,
  "tagline": "Calm, clinical, kind",
  "description": "Science-backed skincare without the jargon.",
  "tone": [
    "warm",
    "expert"
  ],
  "formality": 40,
  "emoji_usage": "light",
  "language": "en",
  "audience": "Women 25–40 who read ingredient lists",
  "values": "Honesty over hype",
  "do_list": [
    "Name the key ingredient"
  ],
  "dont_list": [
    "Promise overnight results"
  ],
  "banned_words": [
    "miracle"
  ],
  "sample_posts": [],
  "hashtag_style": "minimal",
  "cta_style": "Soft invitation",
  "is_default": false,
  "status": "archived",
  "team_id": null,
  "created_at": "2026-10-01T10:00:00.000Z",
  "updated_at": "2026-10-20T10:00:00.000Z",
  "platform": false,
  "key": null,
  "content_type": null
}
POST/v1/personas/{id}/restore

Restore a persona

Makes an archived persona active again. Counts toward the plan's persona limit.

Scopepersonas:writeMCP toolrestore_persona
Path parameters
idrequired
stringPersona ID
Request
curl -X POST "https://croud.ai/api/v1/personas/id_123/restore" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0prs001",
  "object": "persona",
  "name": "Lumen voice",
  "avatar_url": null,
  "tagline": "Calm, clinical, kind",
  "description": "Science-backed skincare without the jargon.",
  "tone": [
    "warm",
    "expert"
  ],
  "formality": 40,
  "emoji_usage": "light",
  "language": "en",
  "audience": "Women 25–40 who read ingredient lists",
  "values": "Honesty over hype",
  "do_list": [
    "Name the key ingredient"
  ],
  "dont_list": [
    "Promise overnight results"
  ],
  "banned_words": [
    "miracle"
  ],
  "sample_posts": [],
  "hashtag_style": "minimal",
  "cta_style": "Soft invitation",
  "is_default": false,
  "status": "active",
  "team_id": null,
  "created_at": "2026-10-01T10:00:00.000Z",
  "updated_at": "2026-10-20T10:00:00.000Z",
  "platform": false,
  "key": null,
  "content_type": null
}
POST/v1/personas/{id}/default

Make a persona the default

The default persona writes AI content when no persona is chosen and no voice is set for the content type. One per workspace; the persona must be active.

Scopepersonas:writeMCP toolset_default_persona
Path parameters
idrequired
stringPersona ID
Request
curl -X POST "https://croud.ai/api/v1/personas/id_123/default" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0prs001",
  "object": "persona",
  "name": "Lumen voice",
  "avatar_url": null,
  "tagline": "Calm, clinical, kind",
  "description": "Science-backed skincare without the jargon.",
  "tone": [
    "warm",
    "expert"
  ],
  "formality": 40,
  "emoji_usage": "light",
  "language": "en",
  "audience": "Women 25–40 who read ingredient lists",
  "values": "Honesty over hype",
  "do_list": [
    "Name the key ingredient"
  ],
  "dont_list": [
    "Promise overnight results"
  ],
  "banned_words": [
    "miracle"
  ],
  "sample_posts": [],
  "hashtag_style": "minimal",
  "cta_style": "Soft invitation",
  "is_default": true,
  "status": "active",
  "team_id": null,
  "created_at": "2026-10-01T10:00:00.000Z",
  "updated_at": "2026-10-20T10:00:00.000Z",
  "platform": false,
  "key": null,
  "content_type": null
}
DELETE/v1/personas/{id}

Delete a persona

Permanently deletes an archived workspace persona. Creatives and campaigns that used it keep their content; their persona link is cleared.

Scopepersonas:writeMCP tooldelete_persona
Path parameters
idrequired
stringPersona ID
Request
curl -X DELETE "https://croud.ai/api/v1/personas/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0prs001",
  "object": "persona",
  "deleted": true
}
GET/v1/personas/voices

Voices by content type

For every content type (see GET /v1/reference/content_type): the workspace's chosen voice, the platform default, and auto_voice, the persona POST /v1/ai/generate uses when persona_id is omitted (source: workspace_type | platform_type | workspace_default).

Scopepersonas:readMCP toolget_content_type_voices
Request
curl "https://croud.ai/api/v1/personas/voices" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "content_type_voices",
  "data": [
    {
      "content_type": "education",
      "label": "How-to & tips",
      "goal": "saves",
      "workspace_voice": null,
      "platform_voice": {
        "id": "cmf0prs101",
        "name": "Practical teacher"
      },
      "auto_voice": {
        "id": "cmf0prs101",
        "name": "Practical teacher",
        "platform": true,
        "source": "platform_type"
      }
    },
    {
      "content_type": "promo",
      "label": "Offer & promo",
      "goal": "clicks",
      "workspace_voice": {
        "id": "cmf0prs001",
        "name": "Lumen voice",
        "platform": false
      },
      "platform_voice": {
        "id": "cmf0prs102",
        "name": "Straight shooter"
      },
      "auto_voice": {
        "id": "cmf0prs001",
        "name": "Lumen voice",
        "platform": false,
        "source": "workspace_type"
      }
    }
  ]
}
PUT/v1/personas/voices

Set voices by content type

Choose the voice for one or more content types: { "voices": { "education": "<persona id>", "promo": null } }. Any workspace persona or platform voice works; null goes back to the platform default. Types you leave out are unchanged.

Scopepersonas:writeMCP toolset_content_type_voices
Body
voicesrequired
objectcontent_type key → persona id, or null for the platform default
Request
curl -X PUT "https://croud.ai/api/v1/personas/voices" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"voices":{"education":"cmf0prs001","promo":null}}'
Response · 200
{
  "object": "content_type_voices",
  "data": [
    {
      "content_type": "education",
      "label": "How-to & tips",
      "goal": "saves",
      "workspace_voice": null,
      "platform_voice": {
        "id": "cmf0prs101",
        "name": "Practical teacher"
      },
      "auto_voice": {
        "id": "cmf0prs101",
        "name": "Practical teacher",
        "platform": true,
        "source": "platform_type"
      }
    },
    {
      "content_type": "promo",
      "label": "Offer & promo",
      "goal": "clicks",
      "workspace_voice": {
        "id": "cmf0prs001",
        "name": "Lumen voice",
        "platform": false
      },
      "platform_voice": {
        "id": "cmf0prs102",
        "name": "Straight shooter"
      },
      "auto_voice": {
        "id": "cmf0prs001",
        "name": "Lumen voice",
        "platform": false,
        "source": "workspace_type"
      }
    }
  ]
}
Reference

AI

Generate captions, hashtags, scripts and ideas. Generations route automatically (your own key, else platform models with fallbacks); list models with `GET /v1/ai/models` and pass a `ref` as `model` to pick one.

POST/v1/ai/generate

Generate content

Generate captions, hashtags, ideas, scripts, rewrites or image prompts. content_type (see GET /v1/reference/content_type) sets the caption length, hashtag count, structure and call to action; a template's category is used when it's omitted. Without persona_id the voice is picked automatically: the workspace's voice for the content type, else the platform voice for it, else the workspace default (see GET /v1/personas/voices); persona_id: null writes without a persona. Every generation uses the brand's saved details (brand kit, then the workspace profile: name, Instagram username, website, description, industry); campaign_id adds that campaign's objective, category, landing page and description. The response says which voice wrote it (persona.source) and whether a rule-fixing pass ran (repaired). Uses the workspace's BYOK key when set (no credits), otherwise AI credits per variation at the platform's current rates (credits_charged).

Scopeai:generateMCP toolgenerate_content
Body
kindrequired
"caption" | "hashtags" | "ideas" | "script" | "rewrite" | "image_prompt"caption | hashtags | ideas | script | rewrite | image_prompt
brief
stringWhat you want, in a sentence or two
content_type
string | nullContent type key, e.g. education, promo, ugc
persona_id
anyPersona or platform voice ID. Omit for Auto (voice for the content type); null for no persona
template_id
anyStart from a template; brief may then be empty
format
anyTarget format key, e.g. ig_reel
campaign_id
string | nullCampaign the copy is for: its objective, category, landing page and description are added to the prompt (404 when outside your workspace or team)
variables
objectTemplate variables
variations
integer
provider
stringForce a provider (see GET /v1/ai/providers); your key for it when you have one, else the platform's
model
string | objectA specific model: "provider:model" (e.g. "openrouter:anthropic/claude-haiku-5.5") or { provider, model }. Must be listed by GET /v1/ai/models; credits use that model's multiplier
Request
curl -X POST "https://croud.ai/api/v1/ai/generate" \
  -H "Authorization: Bearer $CROUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"kind":"caption","brief":"Launch post for our vitamin C serum, 20% off this week","content_type":"product_launch","format":"ig_reel","variations":2,"model":"openrouter:anthropic/claude-haiku-5.5"}'
Response · 201
{
  "object": "ai_generation_result",
  "id": "cmf0gen001",
  "outputs": [
    {
      "text": "Glow season starts now. Our vitamin C serum is 20% off this week.",
      "hashtags": [
        "skincare",
        "vitaminc"
      ],
      "cta": "Shop now"
    }
  ],
  "provider": "anthropic",
  "model": "claude-sonnet-5-5",
  "used_byok": false,
  "credits_charged": 2,
  "persona": {
    "id": "cmf0prs101",
    "name": "Launch insider",
    "source": "platform_type"
  },
  "content_type": "product_launch",
  "repaired": false,
  "fallback_used": false
}
GET/v1/ai/models

List AI models

Models this workspace can generate with. platform models are paid with AI credits: credits is what one generation of each kind costs with that model (the kind's credits × the model's multiplier); available: false means the model is visible but not included in your plan. byok lists models reachable through your own provider keys (no credits). Pass a model's ref as model to POST /v1/ai/generate. current is where generations go when no model is given.

Scopeai:generateMCP toollist_ai_models
Request
curl "https://croud.ai/api/v1/ai/models" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "object": "ai_model",
      "ref": "openrouter:anthropic/claude-haiku-5.5",
      "provider": "openrouter",
      "provider_name": "OpenRouter",
      "model": "anthropic/claude-haiku-5.5",
      "label": "Claude Haiku 5.5",
      "description": "Anthropic via OpenRouter. Fast and inexpensive.",
      "tier": "standard",
      "context_length": 1000000,
      "credit_multiplier": 1,
      "credits": {
        "caption": 1,
        "design": 8
      },
      "available": true,
      "reason": null,
      "billing": "credits"
    }
  ],
  "byok": [
    {
      "key_id": "cmf0key001",
      "key_label": "Our OpenAI key",
      "provider": "openai",
      "provider_name": "OpenAI",
      "is_default": true,
      "default_model": "gpt-5.6-terra",
      "models": [
        {
          "ref": "openai:gpt-5.6-terra",
          "model": "gpt-5.6-terra",
          "label": "GPT-5.6 Terra",
          "tier": "standard"
        }
      ]
    }
  ],
  "current": {
    "mode": "platform",
    "provider": "openrouter",
    "model": "anthropic/claude-haiku-5.5",
    "label": "Claude Haiku 5.5"
  }
}
GET/v1/ai/providers

List AI providers

Providers you can bring your own key for (Settings → AI provider keys), with where to create a key, the key format and the models offered. requires_base_url providers (Azure OpenAI) also need your resource URL; free_text_models providers accept any model id their model list contains (checked when the key is saved). byok_enabled says whether your plan includes your own keys.

Scopeai:generateMCP toollist_ai_providers
Request
curl "https://croud.ai/api/v1/ai/providers" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "byok_enabled": true,
  "data": [
    {
      "object": "ai_provider",
      "key": "openrouter",
      "name": "OpenRouter",
      "description": "One key for hundreds of models from Anthropic, OpenAI, Google, Meta and more.",
      "key_prefix": "sk-or-",
      "key_placeholder": "sk-or-v1-…",
      "docs_url": "https://openrouter.ai/docs/quickstart",
      "dashboard_url": "https://openrouter.ai/settings/keys",
      "requires_base_url": false,
      "supports_model_list": true,
      "free_text_models": true,
      "default_model": "anthropic/claude-haiku-5.5",
      "models": [
        {
          "id": "anthropic/claude-haiku-5.5",
          "label": "Claude Haiku 5.5",
          "tier": "standard"
        }
      ]
    }
  ]
}
GET/v1/ai/generations

List generations

AI generation history for the workspace, newest first.

Scopeai:generateMCP toollist_generations
Query parameters
limit
integerPage size, 1–100 (default 25)
cursor
stringnext_cursor from the previous page
kind
"caption" | "hashtags" | "ideas" | "script" | "rewrite" | "image_prompt" | "variant" | "design" | "design_edit"
persona_id
string
content_type
stringContent type key (see GET /v1/reference/content_type)
status
"succeeded" | "failed"
Request
curl "https://croud.ai/api/v1/ai/generations" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0gen001",
      "object": "ai_generation",
      "kind": "caption",
      "status": "succeeded",
      "error": null,
      "persona": {
        "id": "cmf0prs001",
        "name": "Lumen voice"
      },
      "content_type": "promo",
      "template_id": null,
      "outputs": [
        {
          "text": "Glow season starts now.",
          "hashtags": [
            "skincare"
          ],
          "cta": "Shop now"
        }
      ],
      "provider": "anthropic",
      "model": "claude-sonnet-5-5",
      "used_byok": false,
      "credits_charged": 1,
      "source": "api",
      "created_at": "2026-10-28T10:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
GET/v1/ai/generations/{id}

Get a generation

One AI generation with its outputs.

Scopeai:generate
Path parameters
idrequired
stringGeneration ID
Request
curl "https://croud.ai/api/v1/ai/generations/id_123" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "id": "cmf0gen001",
  "object": "ai_generation",
  "kind": "caption",
  "status": "succeeded",
  "error": null,
  "persona": null,
  "content_type": null,
  "template_id": null,
  "outputs": [],
  "provider": "anthropic",
  "model": "claude-sonnet-5-5",
  "used_byok": false,
  "credits_charged": 1,
  "source": "api",
  "created_at": "2026-10-28T10:00:00.000Z"
}
Reference

Analytics

Performance reporting.

GET/v1/analytics

Get analytics

Performance over the last 7, 30 or 90 days with deltas against the previous period and a daily series. side=advertiser: spend, impressions, reach, engagements, clicks, top accounts and per-campaign KPIs. side=creator: earnings, approvals and per-account / per-advertiser breakdowns.

Scopeanalytics:readMCP toolget_analytics
Query parameters
siderequired
"advertiser" | "creator"Which side of the marketplace to report on
days
integer
Request
curl "https://croud.ai/api/v1/analytics?side=advertiser" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "analytics",
  "side": "advertiser",
  "days": 30,
  "totals": {
    "spend_cents": 310000,
    "impressions": 402000,
    "reach": 288000,
    "engagements": 21400,
    "clicks": 3100
  },
  "deltas": {
    "spend_cents": 12.4,
    "impressions": 8.1,
    "reach": 5.6,
    "engagements": -2.3,
    "clicks": 14
  },
  "series": [
    {
      "date": "2026-10-27",
      "spend_cents": 12000,
      "impressions": 14800,
      "reach": 10200,
      "engagements": 790,
      "clicks": 104
    }
  ],
  "top_accounts": [],
  "per_campaign": []
}
Reference

Wallet

Balances and the transaction ledger.

GET/v1/wallet

Get wallet balances

Balances in the platform currency (cents). Advertisers: available funds new placements, reserved is held for approved placements and open-campaign escrow (marketplace fee included). Creators: pending_earnings settle when placements complete; withdrawable_cents (settled earnings not yet paid out or spent) can be paid out. Deposits are never withdrawable.

Scopewallet:read or analytics:readMCP toolget_wallet
Request
curl "https://croud.ai/api/v1/wallet" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "wallet",
  "currency": "USD",
  "available_cents": 1250000,
  "withdrawable_cents": 0,
  "reserved_cents": 90000,
  "pending_payouts_cents": 0,
  "pending_earnings_cents": 0,
  "lifetime_earnings_cents": 0,
  "lifetime_spend_cents": 310000,
  "lifetime_deposits_cents": 1650000
}
GET/v1/wallet/transactions

List wallet transactions

The wallet ledger, newest first. Amounts are signed cents: holds and charges are negative, deposits and earnings positive.

Scopewallet:read or analytics:readMCP toollist_wallet_transactions
Query parameters
limit
integerPage size, 1–100 (default 25)
cursor
stringnext_cursor from the previous page
type
"deposit" | "reserve" | "hold" | "release" | "charge" | "earning" | "platform_fee" | "payout" | "refund" | "adjustment"[] | stringComma-separated transaction types
status
"pending" | "settled" | "failed" | "reversed"[] | stringComma-separated statuses
campaign_id
string
placement_id
string
Request
curl "https://croud.ai/api/v1/wallet/transactions" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "cmf0txn001",
      "object": "wallet_transaction",
      "type": "hold",
      "amount_cents": -45000,
      "currency": "USD",
      "status": "pending",
      "campaign_id": "cmf0cmp001",
      "placement_id": "cmf0plc001",
      "payout_id": null,
      "description": "Hold for @maya.creates",
      "created_at": "2026-10-28T11:00:00.000Z"
    }
  ],
  "has_more": true,
  "next_cursor": "cmf0txn001"
}
Reference

Reference data

Valid keys for categories, countries, objectives and decline reasons.

GET/v1/reference/{list}

List reference values

Valid keys for admin-managed lists: content_category (creator niches, campaign targeting), ad_category (what a campaign promotes; creator policies allow or block these), country, campaign_objective, decline_reason creative_angle (messaging angles for unique posts per creator: hook, guidance, suited_categories, blocked_ad_categories, default_selected), content_type (kinds of posts for AI writing and caption template categories: goal, persona_key, caption_min/caption_max characters, hashtag_min/hashtag_max, emoji, structure, cta, slide_min/slide_max) and persona_tone (tones for personas). Keys are stable; retired values keep resolving but can't be used for new writes. Any API key can read these.

Scopeany keyMCP toolget_reference_data
Path parameters
listrequired
"content_category" | "ad_category" | "country" | "campaign_objective" | "decline_reason" | "creative_angle" | "content_type" | "persona_tone" | "payout_method" | "dispute_reason" | "report_reason" | "cta" | "design_template_category"content_category | ad_category | country | campaign_objective | decline_reason | creative_angle | content_type | persona_tone | payout_method | dispute_reason | report_reason | cta | design_template_category
Query parameters
include_retired
boolean | "0" | "1" | "true" | "false"Include retired values (to label stored data)
Request
curl "https://croud.ai/api/v1/reference/list" \
  -H "Authorization: Bearer $CROUD_API_KEY"
Response · 200
{
  "object": "reference_list",
  "list": "ad_category",
  "label": "Ad categories",
  "data": [
    {
      "key": "beauty",
      "label": "Beauty & skincare",
      "description": null,
      "active": true,
      "metadata": {
        "sensitive": false,
        "default_blocked": false
      }
    },
    {
      "key": "gambling",
      "label": "Gambling",
      "description": null,
      "active": true,
      "metadata": {
        "sensitive": true,
        "default_blocked": true
      }
    }
  ]
}
Webhooks

Events

Add endpoints in Settings → Developers → Webhooks (Pro and above). Croud POSTs a JSON event to each subscribed endpoint and expects a 2xx within 10 seconds. Failed deliveries are retried with exponential backoff (30s, 2m, 8m, 32m) for up to 5 attempts; an endpoint that fails 20 times in a row is disabled and admins are notified.

Event payload
{
  "id": "evt_6u2Jx1bQ0nF4kT9a",
  "type": "placement.approved",
  "created": "2026-10-28T11:00:00.000Z",
  "workspace_id": "cmf0ws0001",
  "data": {
    "placement_id": "cmf0plc001",
    "account": "maya.creates",
    "scheduled_at": "2026-11-02T15:00:00.000Z",
    "auto": false
  }
}
campaign.createdcampaign.updatedcampaign.launchedcampaign.pausedcampaign.completedplacement.requestedplacement.approvedplacement.rejectedplacement.changes_requestedplacement.publishedplacement.failedplacement.completedplacement.counteredplacement.counter_acceptedplacement.offer_revisedplacement.appliedplacement.withdrawnplacement.rescheduledaccount.analyzedaccount.connectedaccount.disconnectedaccount.policy_updatedcreative.createdcreative.variant_readycreative.variant_failedpersona.createdpayout.requestedpayout.paidpayout.failedpayout.canceleddispute.openeddispute.resolvedsubscription.updatedmember.joineddesign.createddesign.exportedbrand_kit.createdbrand_kit.updated

Deliveries can arrive more than once and out of order. Deduplicate on Croud-Delivery or the event id, and fetch the latest state from the API when ordering matters. Payloads for the offer and analysis events are listed in Open campaigns & direct requests, design and brand kit events in Design studio, and variant events in Unique posts.

Webhooks

Verifying signatures

Each request carries Croud-Event, Croud-Delivery and Croud-Signature: t=<unix>,v1=<hex>. Compute HMAC-SHA256 over t + "." + rawBody with the endpoint's signing secret, compare in constant time, and reject timestamps older than five minutes.

Node.js · Express
import crypto from "node:crypto";
import express from "express";

const app = express();
const SECRET = process.env.CROUD_WEBHOOK_SECRET; // whsec_…
const TOLERANCE_SECONDS = 300;

// Use the raw body: re-serialized JSON won't match the signature.
app.post("/webhooks/croud", express.raw({ type: "application/json" }), (req, res) => {
  const header = req.get("Croud-Signature") ?? "";
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const timestamp = Number(parts.t);
  const expected = crypto
    .createHmac("sha256", SECRET)
    .update(`${parts.t}.${req.body}`)
    .digest("hex");

  const valid =
    parts.v1?.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected)) &&
    Math.abs(Date.now() / 1000 - timestamp) < TOLERANCE_SECONDS;
  if (!valid) return res.status(400).send("Invalid signature");

  const event = JSON.parse(req.body.toString("utf8"));
  // Deduplicate on req.get("Croud-Delivery") / event.id, then handle event.type
  console.log(event.type, event.data);
  res.sendStatus(200);
});

app.listen(3000);
MCP

Model Context Protocol

The MCP server lets AI agents use Croud directly. It speaks Streamable HTTP (stateless, JSON responses) at the endpoint below and authenticates with the same API keys — create a restricted key per agent. Available on Pro and above.

Endpoint
https://croud.ai/api/mcp

Run once; add --scope user to make it available in every project.

Terminal
claude mcp add --transport http croud https://croud.ai/api/mcp \
  --header "Authorization: Bearer <YOUR_API_KEY>"

Tool calls are authorized exactly like REST requests: scopes, the creator's role and plan limits all apply, and failures come back as tool errors (isError: true) with the same message the REST API would return.

MCP

Tools

whoamiRead · any key
Identify the workspace, plan, scopes and permissions of the connected Croud API key. Call this first to learn which side (creator / advertiser) the workspace operates on.
get_usageRead · any key
AI credit balance and this period's API / MCP / AI generation usage for the workspace.
list_formatsRead · templates:read
List Instagram ad formats (feed image, carousel, reel, story…) with specs and whether this workspace can launch them.
list_templatesRead · templates:read
List content templates (caption structure, hashtags, CTA, media guidance) available to this workspace. Filter by format, source or category.
get_workspaceRead · any key
Read the workspace profile (name, logo, website, Instagram username, description, industry, country, time zone).
update_workspaceWrite · workspace:write
Update the workspace profile: name, logo URL, website, Instagram username, description, industry, country or time zone. Omitted fields are unchanged.
list_membersRead · members:read
List workspace members with their role, teams and status.
list_invitationsRead · members:read
List pending and expired workspace invitations.
invite_membersWrite · members:write
Email workspace invitations to one or more addresses with a role (system role key or custom role id).
resend_invitationWrite · members:write
Email a pending or expired workspace invitation again with a fresh 7-day link.
revoke_invitationDestructive · members:write
Cancel a pending workspace invitation so its link stops working.
update_memberWrite · members:write
Change a workspace member's role (system role key or custom role id), access scope or teams.
remove_memberDestructive · members:write
Remove a member from the workspace (revokes the API keys they created).
list_webhooksRead · webhooks:write
List the workspace's webhook endpoints, their events and recent delivery counts.
create_webhookWrite · webhooks:write
Register an https webhook endpoint for event types; returns its signing secret once.
get_webhookRead · webhooks:write
Get one webhook endpoint.
update_webhookWrite · webhooks:write
Change a webhook endpoint's URL, description, events or enabled state.
delete_webhookDestructive · webhooks:write
Delete a webhook endpoint and its delivery history.
test_webhookWrite · webhooks:write
Send a signed test event to a webhook endpoint and report whether it answered 2xx.
get_templateRead · templates:read
Get one caption template (structure, hashtags, CTA, variables).
create_templateWrite · templates:write
Create a workspace caption template (format, caption with {{variables}}, hashtags, CTA), as a draft or published.
update_templateWrite · templates:write
Edit a workspace caption template; omitted fields are unchanged.
publish_templateWrite · templates:write
Publish a workspace caption template so it can be used in creatives.
unpublish_templateWrite · templates:write
Move a workspace caption template back to draft (also restores an archived one).
archive_templateWrite · templates:write
Archive a workspace caption template (can be restored or deleted).
delete_templateDestructive · templates:write
Permanently delete an archived workspace caption template.
list_mediaRead · creatives:read
List images and videos in the media library (filter by type, folder or name).
add_media_from_urlWrite · creatives:write
Download a public image or video URL into the media library so creatives can use it.
delete_mediaDestructive · creatives:write
Delete an unused file from the media library.
list_campaignsRead · campaigns:read
List the workspace's advertiser campaigns with status, budget, placement counts and reach. Filter by status (e.g. live, draft, paused).
create_campaignWrite · campaigns:write
Create a draft advertiser campaign (name, type targeted/open/direct, objective, ad category, optional budget, open-offer price and acceptance mode, collab settings, schedule, targeting, brand kit and unique posts per creator via variants_enabled + variant_config). It is not launched.
get_campaignRead · campaigns:read
Get a campaign with its creatives, placements and performance totals.
update_campaignWrite · campaigns:write
Update campaign fields such as budget, schedule, targeting or landing URL (running campaigns allow a limited set).
delete_campaignDestructive · campaigns:write
Delete a draft campaign that never launched.
archive_campaignWrite · campaigns:write
Archive a draft, completed or canceled campaign.
duplicate_campaignWrite · campaigns:write
Copy a campaign (settings, targeting, creatives) into a new draft.
get_campaign_readinessRead · campaigns:read
Check whether a campaign can launch: blocking issues, warnings, wallet coverage and the placement estimate.
launch_campaignDestructive · campaigns:write
Launch a draft campaign. Requires ready creatives, a budget and enough wallet balance; creates placement requests to matching creators. Spends real money once creators approve.
pause_campaignWrite · campaigns:write
Pause an active or scheduled campaign (no new placement requests).
resume_campaignDestructive · campaigns:write
Resume a paused campaign; newly eligible creators receive requests.
cancel_campaignDestructive · campaigns:write
Cancel a campaign and all of its unpublished placements. Irreversible.
preview_campaign_matchesRead · campaigns:read
Dry-run which creator accounts a campaign would match, with price and the reasons ineligible accounts are excluded.
list_creativesRead · creatives:read
List ad creatives (caption, hashtags, media, format, status). Filter by campaign, format or status.
create_creativeWrite · creatives:write
Create an ad creative (format, caption, hashtags, CTA, link, media URLs), optionally attached to a campaign. status=ready validates it against the format specs.
get_creativeRead · creatives:read
Get one ad creative.
update_creativeWrite · creatives:write
Edit a creative's caption, hashtags, media, CTA or status (draft, ready, archived).
delete_creativeDestructive · creatives:write
Permanently delete an unused creative.
duplicate_creativeWrite · creatives:write
Copy a creative into a new draft, optionally for another campaign.
attach_creative_to_campaignWrite · creatives:write
Add an existing library creative to a campaign (creatives already used by another campaign are copied).
detach_creative_from_campaignWrite · creatives:write
Move a creative out of a campaign back to the library (refused while it has open placements).
render_templateWrite · creatives:write
Fill a content template's variables to get caption, hashtags and CTA for a new creative.
list_campaign_variantsRead · campaigns:read
List the unique per-creator posts (variants) of a campaign with their review status, angle, uniqueness score and placement.
approve_all_variantsWrite · campaigns:write
Approve every unique post waiting for review in a campaign so they are sent to the creators.
approve_variantWrite · campaigns:write
Approve one creator's unique post so it is sent to the creator.
update_variantWrite · campaigns:write
Edit a unique post's caption, hashtags and CTA while it is in review or the creator asked for changes.
regenerate_variantWrite · campaigns:write
Rewrite a creator's unique post in the background, optionally with a different angle, design template or notes. Uses AI credits.
use_base_creativeDestructive · campaigns:write
Skip a creator's unique post and send the campaign's base creative instead.
list_brand_kitsRead · creatives:read
List the workspace's brand kits (colors, fonts, logos, handle). The default kit is first.
create_brand_kitWrite · creatives:write
Create a brand kit: name, five hex colors (dark, light, accent, accent_ink, secondary), display/body/mono fonts, optional logos, handle and website.
get_brand_kitRead · creatives:read
Get one brand kit with color contrast warnings.
update_brand_kitWrite · creatives:write
Edit a brand kit's colors, fonts, logos, handle, website or radius.
delete_brand_kitDestructive · creatives:write
Delete a brand kit; designs and campaigns using it move to the next kit.
set_default_brand_kitWrite · creatives:write
Make a brand kit the workspace default.
list_design_templatesRead · creatives:read
List visual design templates (carousels, single posts, stories) with category, supported formats and whether this workspace can use them.
get_design_templateRead · creatives:read
Get one design template with its sample slides and available layouts.
update_design_templateWrite · templates:write
Rename a custom (workspace) design template or change its description, category or tags.
list_layoutsRead · creatives:read or templates:read
List slide layouts (cover, list, quote, stat, cta…) with their content fields and limits, and the canvas formats.
list_designsRead · creatives:read
List designs (branded carousels, posts, stories). Filter by campaign, template, brand kit or status.
create_designWrite · creatives:write
Create a branded design from a design template; with `brief`, AI writes the slides, caption and hashtags (uses AI credits).
get_designRead · creatives:read
Get one design with its slides, caption and hashtags.
update_designWrite · creatives:write
Edit a design: slides, caption, hashtags, format, brand kit, campaign, persona, content type or status (draft, ready, archived).
delete_designDestructive · creatives:write
Permanently delete a design and its export files.
duplicate_designWrite · creatives:write
Copy a design into a new draft.
write_design_with_aiWrite · creatives:write
Have AI write a design's slides, caption and hashtags from a brief (uses AI credits). apply=false returns a draft without saving.
rewrite_design_slidesWrite · creatives:write
Rewrite some slides of a design with AI (shorter, punchier, more casual, fix overflow, or an instruction), keeping layouts and images. Uses AI credits.
design_caption_optionsWrite · creatives:write
Get AI caption options (with hashtags) for a design's slides. Nothing is saved; update the design with the one you pick. Uses AI credits.
export_designWrite · creatives:write
Render a design to PNG/JPG/ZIP/PDF (counts toward the monthly export limit). Returns download URLs; save_to_library also adds the images to the media library.
list_design_exportsRead · creatives:read
List a design's recent exports with status and download URLs.
get_design_exportRead · creatives:read
Check an export's status and get its download URLs.
save_design_as_creativeWrite · creatives:write
Turn a design into a draft ad creative (feed image, carousel or story) with its slides as media.
list_placementsRead · placements:read
List placements (ad requests). side=creator lists requests on the workspace's Instagram accounts (filter status=pending_approval for the review inbox); side=advertiser lists placements of the workspace's campaigns.
get_placementRead · placements:read
Get one placement with its creative (caption, hashtags, media), campaign, advertiser and status.
approve_placementDestructive · placements:write
Approve an ad request on one of the workspace's accounts. It is then scheduled for publishing automatically.
reject_placementDestructive · placements:write
Decline an ad request with a reason shown to the advertiser.
request_placement_changesWrite · placements:write
Ask the advertiser to change an ad request (e.g. caption edits) before you approve it.
resubmit_placementWrite · campaigns:write
Advertiser: send a placement in changes_requested back to the creator after updating its creative.
cancel_placementDestructive · campaigns:write
Advertiser: cancel a placement that has not been published yet.
list_placement_messagesRead · placements:read
Read the creator/advertiser conversation on a placement.
send_placement_messageWrite · placements:write or campaigns:write
Send a message to the other party on a placement.
counter_direct_requestWrite · placements:write
Creator: reply to a direct request with your own price. The advertiser then accepts, declines or counters back.
list_opportunitiesRead · accounts:read or placements:read
Creator: list open campaigns the workspace's accounts can accept, with price, earning, requirements, creatives and per-account fit.
get_opportunityRead · accounts:read or placements:read
Creator: get one open campaign with its creatives, requirements and which of your accounts can accept it.
accept_opportunityDestructive · placements:write
Creator: accept an open campaign with one account and creative. Instant campaigns book immediately; review campaigns create an application.
preview_direct_requestRead · marketplace:read
Advertiser: check whether a creator takes direct requests, their rates, and warnings for a campaign/creative/price before sending.
list_requestable_campaignsRead · campaigns:read
Advertiser: campaigns and ready creatives that a direct request can be sent for, with remaining budget.
send_direct_requestDestructive · campaigns:write
Advertiser: send a creator a request for one campaign creative at your price. Reserves the amount from the wallet; spends money once the creator approves.
list_sent_requestsRead · campaigns:read
Advertiser: list direct requests and open-campaign applications; status=action shows counter-offers and applications waiting on you.
get_sent_requestRead · campaigns:read
Advertiser: get a direct request or application with negotiation state, available actions and messages.
respond_to_counter_offerDestructive · campaigns:write
Advertiser: accept, decline or counter a creator's counter-offer on a direct request. Accepting books the post at the counter price.
review_applicationDestructive · campaigns:write
Advertiser: approve or decline a creator's application to an open campaign that requires review.
get_reference_dataRead · any key
List valid keys for content categories, ad categories, countries, campaign objectives, decline reasons, creative angles (for unique posts per creator), content types (AI writing rules per kind of post) or persona tones.
list_accountsRead · accounts:read
List the workspace's connected Instagram creator accounts with followers, engagement, approval mode and pending request counts.
get_accountRead · accounts:read
Get a connected account with its full ad policy (content rules, requirements, approval mode) and rate cards.
update_account_settingsWrite · accounts:write
Change an account's marketplace listing, purpose or team.
get_account_policyRead · accounts:read
Get an account's ad policy: accepted categories, blocked keywords, minimum price, pacing, posting windows and approval mode.
update_account_policyWrite · accounts:write
Update which ads an account accepts (categories, keywords, advertisers, formats, disclosure, AI content). Omitted fields are unchanged.
update_account_requirementsWrite · accounts:write
Update an account's minimum price/budget, lead time, frequency caps, approval SLA and posting windows. Omitted fields are unchanged.
update_approval_settingsWrite · accounts:write
Set an account's approval mode (manual, rules, auto), optional auto-approval rules, and who may send direct requests (anyone, eligible_only, off).
list_rate_cardsRead · accounts:read
Get an account's price per post for each ad format.
update_rate_cardsWrite · accounts:write
Set an account's price per post for one or more formats: automatic (suggested) or manual price in cents (minimum 500), plus optional collab add-on. Omitted fields keep their current values.
get_account_insightsRead · accounts:read
Get an account's analyzed content categories, description, recent-post stats and suggested price per format with the pricing breakdown.
update_account_profileWrite · accounts:write
Set an account's content categories or advertiser-facing description (marked manual), or reset either to the analysis results.
analyze_accountWrite · accounts:write
Queue a fresh analysis of an account's recent posts; results arrive via get_account_insights or the account.analyzed webhook.
sync_accountWrite · connections:write
Refresh a connected account's followers, engagement and profile from Instagram.
disconnect_accountDestructive · connections:write
Disconnect a connected Instagram account; open and scheduled placements on it are closed.
generate_contentWrite · ai:generate
Generate Instagram copy (caption, hashtags, ideas, script, rewrite, image prompt) using the brand's saved details. Pass content_type (e.g. education, promo, ugc) for the right length, hashtags and voice; omit persona_id to let the content type pick the voice; pass campaign_id to write for a campaign's objective and landing page. Omit model for automatic routing, or pass a ref from list_ai_models (e.g. openrouter:anthropic/claude-haiku-5.5) to pick one. Consumes AI credits (times the model's multiplier) unless it runs on the workspace's own key.
list_ai_modelsRead · ai:generate
List the AI models this workspace can use (platform credits or its own keys), with credits per generation kind. Pass a model's ref as `model` to generate_content.
list_ai_providersRead · ai:generate
List the AI providers a workspace can add its own key for, with key hints and models.
list_generationsRead · ai:generate
List previous AI generations with their outputs.
search_creatorsRead · marketplace:read
Search the creator marketplace by niche, country, followers, engagement, format, price, approval mode, availability and collab support.
get_creator_profileRead · marketplace:read
Get a marketplace creator's stats, audience, rate card, track record and policy summary.
get_analyticsRead · analytics:read
Advertiser (spend, reach, engagement, clicks) or creator (earnings, approvals) analytics for 7, 30 or 90 days.
list_personasRead · personas:read
List voices available for AI generation: the workspace's personas and the platform voices (platform: true). Each has tone, do/don't lists and sample posts.
get_personaRead · personas:read
Get one brand voice persona.
create_personaWrite · personas:write
Create a brand voice persona (tone, formality, emoji and hashtag style, do/don't lists, sample posts).
update_personaWrite · personas:write
Edit a persona's voice settings. Omitted fields are unchanged.
duplicate_personaWrite · personas:write
Copy a persona or platform voice into the workspace so it can be edited.
archive_personaWrite · personas:write
Archive a workspace persona so it's no longer used for AI generation (can be restored).
restore_personaWrite · personas:write
Restore an archived workspace persona.
set_default_personaWrite · personas:write
Make an active workspace persona the default voice for AI generation.
delete_personaDestructive · personas:write
Permanently delete an archived workspace persona.
get_content_type_voicesRead · personas:read
Which persona writes each content type when generation is on Auto, and the platform default for each.
set_content_type_voicesWrite · personas:write
Pick which persona writes each content type when generation is on Auto (null = platform default).
get_walletRead · wallet:read or analytics:read
Wallet balances: available funds, reserved holds, pending earnings and lifetime totals (in cents).
list_wallet_transactionsRead · wallet:read or analytics:read
Wallet ledger entries (deposits, holds, charges, earnings, payouts), newest first, with cursor pagination.
list_payoutsRead · wallet:read
Creator payout requests and their status, newest first.
list_payout_methodsRead · wallet:read
Payout methods creators can choose (admin-managed), with what `destination` to send and the usual processing time. Automatic methods (Stripe) need a connected Stripe account.
request_payoutDestructive · payouts:write
Request a payout of settled creator earnings.
cancel_payoutDestructive · payouts:write
Cancel a payout that is still `pending` (not yet approved). The amount returns to the withdrawable balance.
open_disputeWrite · placements:write or campaigns:write
Report a problem with a booked post (removed early, not as approved, payment not released…).
list_disputesRead · placements:read
Disputes on this workspace's placements (as advertiser or creator), newest first.