Brand key required
Campaigns
A campaign is a public application form creators apply to. New campaigns pass an automated quality review before going live; your first campaign is included, additional ones consume a campaign credit.
List campaigns
GET/v1/campaigns
| Parameter | Type | Description |
|---|---|---|
| status | string | Filter by status: live, pending_review, or any status you have set. |
| page / limit | integer | Standard pagination (default 20, max 100). |
request
curl "https://api.ugcroster.com/v1/campaigns?status=live" \
-H "Authorization: Bearer rsk_brand_key"response 200
{
"data": [
{
"id": "form_xyz789",
"title": "Summer Skincare Launch",
"status": "live",
"brand_name": "Glow Skincare",
"campaign_type": "organic_ugc",
"compensation_label": "$250 per video",
"applications_closed": false,
"applicant_count": 47,
"hired_count": 8,
"created_at": "2026-05-20T09:00:00Z"
}
],
"pagination": { "page": 1, "limit": 20, "total": 12, "has_more": false }
}Create a campaign
POST/v1/campaigns
| Field | Type | Description |
|---|---|---|
| title | string | Required. Campaign title. |
| questions | array | Required, at least one. Each item: { id, type, question }, plus options: string[] when type is "single_choice". |
| campaign_type | string | organic / ugc / organic_ugc → organic_ugc; paid / paid_ads → paid_ads; influencer; affiliate. Default organic_ugc. |
| full_description | string | Long-form campaign description shown to creators. |
| compensation_label | string | Human-readable pay line, e.g. "$300 per video". |
| compensation_amount | string | Numeric amount as a string. |
| brand_name / website | string | Defaults to your brand profile when omitted. |
| creator_type / niche / platform | string | Targeting labels for the marketplace listing. |
| content_needed / budget_per_creator / timeline | string | Optional listing details. |
| start_date / end_date | string | ISO dates for the campaign window. |
| ships_product | boolean | Whether product is shipped to creators. |
request
curl -X POST "https://api.ugcroster.com/v1/campaigns" \
-H "Authorization: Bearer rsk_brand_key" \
-H "Content-Type: application/json" \
-d '{
"title": "Fall Collection UGC",
"campaign_type": "ugc",
"full_description": "We need authentic unboxing content for our fall line.",
"compensation_label": "$300 per video",
"platform": "tiktok",
"questions": [
{ "id": "q1", "type": "text", "question": "Link your best UGC example" },
{ "id": "q2", "type": "single_choice", "question": "Preferred platform",
"options": ["TikTok", "Instagram"] }
]
}'response 200
{
"data": {
"id": "form_new456",
"title": "Fall Collection UGC",
"status": "pending_review",
"campaign_type": "organic_ugc",
"auto_approved": false
}
}Every submission goes through the same deterministic quality gate as the brand portal. Failures return 400 VALIDATION_ERROR with an issues array explaining each problem. If the automated review passes, status comes back live and auto_approved: true; otherwise the campaign stays pending_review until manually approved. Creating a second campaign without a purchased credit returns 402 campaign_credit_required.
Get a campaign
GET/v1/campaigns/{id}
Returns the campaign plus its raw applicants and hired creators in one call.
response 200
{
"data": {
"campaign": {
"id": "form_xyz789",
"title": "Summer Skincare Launch",
"status": "live",
"brand_name": "Glow Skincare",
"campaign_type": "organic_ugc",
"compensation_label": "$250 per video",
"compensation_amount": "250",
"full_description": "Authentic skincare content for summer.",
"applications_closed": false,
"questions": [ { "id": "q1", "type": "text", "question": "…" } ],
"created_at": "2026-05-20T09:00:00Z"
},
"applicants": [
{
"id": "app_001",
"respondent_email": "emma@example.com",
"user_id": "user_123",
"responses": { "q1": "https://instagram.com/p/abc123" },
"submitted_at": "2026-06-01T12:00:00Z"
}
],
"hired_creators": [
{ "id": "hire_001", "creator_email": "emma@example.com",
"creator_name": "Emma Chen", "hired_at": "2026-06-03T09:00:00Z" }
]
}
}Update a campaign
PATCH/v1/campaigns/{id}
| Field | Type | Description |
|---|---|---|
| title | string | New title (non-empty). |
| full_description | string | New description; empty string clears it. |
| applications_closed | boolean | Close or reopen applications without archiving. |
| applicant_cap | integer | null | Optional positive cap on applicants; null clears it. |
| compensation_label / compensation_amount | string | Pay line and amount. |
| campaign_type | string | Same accepted values as create. |
| website / brand_name / creator_type / niche / platform | string | Listing fields. |
| content_needed / budget_per_creator / timeline | string | Listing details. |
| start_date / end_date | string | null | ISO dates; null clears. |
| ships_product | boolean | Product shipping flag. |
request
curl -X PATCH "https://api.ugcroster.com/v1/campaigns/form_xyz789" \
-H "Authorization: Bearer rsk_brand_key" \
-H "Content-Type: application/json" \
-d '{ "applications_closed": true, "compensation_label": "$350 per video" }'response 200
{
"data": {
"id": "form_xyz789",
"applications_closed": true,
"compensation_label": "$350 per video",
"updated_at": "2026-06-13T14:35:00Z"
}
}Archive a campaign
DELETE/v1/campaigns/{id}
Soft-deletes the campaign: it is hidden from the marketplace and excluded from listings, but its applications and hires remain readable. Archived campaigns no longer count against your included campaign.
request
curl -X DELETE "https://api.ugcroster.com/v1/campaigns/form_xyz789" \
-H "Authorization: Bearer rsk_brand_key"response 200
{ "data": { "id": "form_xyz789", "deleted": true } }List a campaign’s applications
GET/v1/campaigns/{id}/applications
| Parameter | Type | Description |
|---|---|---|
| status | string | Filter: pending, approved, rejected, hired. |
| page / limit | integer | Standard pagination. |
response 200
{
"data": [
{
"id": "app_001",
"respondent_email": "emma@example.com",
"creator_name": "Emma Chen",
"user_id": "user_123",
"name": "Emma Chen",
"email": "emma@example.com",
"portfolio": "https://emmachen.com",
"social_link": "https://instagram.com/emmachen",
"responses": { "q1": "https://instagram.com/p/abc123" },
"status": "pending",
"submitted_at": "2026-06-01T12:00:00Z"
}
],
"pagination": { "page": 1, "limit": 20, "total": 47, "has_more": true }
}name, email, portfolio and social_linkare extracted from the applicant’s answers by matching question labels. The raw answers are always available under responses. Creators who were hired report status: "hired" regardless of the stored application status.