Brand key required
Affiliates & commissions
Give creators discount codes or tracked links, watch clicks convert into attributed revenue, then approve, reject, or pay out the resulting commission events.
Affiliate overview
GET/v1/affiliates
One row per affiliate link with lifetime stats, plus a summary of totals. Standard pagination.
request
curl "https://api.ugcroster.com/v1/affiliates" \
-H "Authorization: Bearer rsk_brand_key"response 200
{
"data": [
{
"id": "link_001",
"creator_email": "emma@example.com",
"creator_name": "Emma Chen",
"campaign_id": null,
"type": "discount_code",
"value": "EMMA15",
"clicks": 1847,
"conversions": 93,
"revenue": 4650.00,
"commission": 697.50,
"commission_rate": 15,
"currency": "USD",
"platform": null,
"last_sync_at": "2026-06-13T06:00:00Z",
"created_at": "2026-03-15T10:00:00Z"
}
],
"pagination": { "page": 1, "limit": 20, "total": 42, "has_more": true },
"summary": {
"total_revenue": 24650.00, "total_commissions": 3697.50,
"total_clicks": 18470, "total_conversions": 930
}
}Links & codes
GET/v1/affiliates/links
| Parameter | Type | Description |
|---|---|---|
| creator_email | string | Filter to one creator. |
| page / limit | integer | Standard pagination. |
Items match the affiliates overview plus url, destination_url, and active.
POST/v1/affiliates/links
Assign an existing code or link to a member of your roster. Supply integration_id to verify an existing store coupon and connect attribution; this does not create a new provider discount. Omit the store only for a manual assignment. Use bulk creation for new store offers.
| Field | Type | Description |
|---|---|---|
| creator_email | string | Required. |
| value | string | Required. The discount code (e.g. "SUMMER20") or the link slug. |
| type | string | "discount_code" (default) or "link". |
| commission_rate | number | Percentage paid to the creator. Default 0. |
| campaign_id / creator_name | string | Optional campaign and creator metadata; the creator must belong to that authorized roster. |
| integration_id | string | Optional connected store. Existing percentage coupons must be active in that store before import. |
| hold_days / attribution_days | integer | Review period 0–90 days and attribution window 1–90 days; both default to 30. |
| destination_url | string | Required for referral links unless value is an HTTPS destination. Connected offers must use the authorized store host. |
| currency | string | Uppercase ISO currency for manual assignments; connected offers use the store currency. |
request
curl -X POST "https://api.ugcroster.com/v1/affiliates/links" \
-H "Authorization: Bearer rsk_brand_key" \
-H "Content-Type: application/json" \
-d '{
"creator_email": "emma@example.com",
"type": "discount_code",
"value": "SUMMER20",
"commission_rate": 20
}'response 200
{
"data": {
"id": "link_002",
"creator_email": "emma@example.com",
"type": "discount_code",
"value": "SUMMER20",
"commission_rate": 20,
"currency": "USD",
"clicks": 0, "conversions": 0, "revenue": 0, "commission": 0,
"active": true,
"created_at": "2026-06-13T15:20:00Z"
}
}PATCH/v1/affiliates/links/{id}
| Field | Type | Description |
|---|---|---|
| value | string | Change the code or slug. |
| commission_rate | number | New rate. |
| active | boolean | Enable or disable the link. |
| creator_name / platform / campaign_id | string | null | Metadata; campaign_id accepts null to unlink. |
| url / destination_url | string | Link-type URLs. |
DELETE/v1/affiliates/links/{id}
response 200
{ "data": { "id": "link_002", "active": false, "deactivated": true } }DELETE is a soft delete: the link is deactivated (active: false) so historical attribution survives.
Discover connected stores
GET/v1/affiliates/integrations
Use the returned store ID as integration_id when importing or generating offers. Optional campaign_id and page/limit filters are supported. The response shows discount/order capabilities, currency, storefront, connection state, webhook health and referral tracking readiness, without access tokens or webhook secrets. Connect or reauthorize stores in the brand web app. MCP provides list_affiliate_stores.
Auto-create roster codes
POST/v1/affiliates/links/bulk
Generate unique tracking codes for selected roster creators or everyone missing a code. Existing assignments for the same creator, campaign, and link type are skipped across your team. Retrying the request preserves existing codes. Generated discount codes must also be added to your store before customers can redeem them; this endpoint returns provisioning: "manual".
| Field | Type | Description |
|---|---|---|
| all_missing | boolean | Set true to process the roster members missing a code. Use exactly one selector. |
| creators | array | Alternative selector: 1–500 objects with an email matching your roster. |
| roster_ids | string[] | Alternative selector: 1–500 roster record IDs belonging to your team. |
| campaign_id | string | Optional campaign owned by your team; limits the roster to that campaign. |
| commission_rate | number | Creator commission percentage, 0–100. Default 0; this is not a customer discount. |
| type | string | discount_code (default), link, or referral_link (alias for link). |
| destination_url | string | HTTP(S) destination; required for referral links. |
request
curl -X POST "https://api.ugcroster.com/v1/affiliates/links/bulk" \
-H "Authorization: Bearer rsk_brand_key" \
-H "Content-Type: application/json" \
-d '{ "all_missing": true, "commission_rate": 15 }'selected creators — alternative request body
{
"creators": [{ "email": "emma@example.com" }, { "email": "sam@example.com" }],
"commission_rate": 15
}response 200
{
"data": {
"created": [{ "id": "auto_…", "creator_email": "emma@example.com", "creator_name": "Emma", "value": "EMMA7BK3RX9Q" }],
"count": 1,
"skipped": [{ "creator_email": "existing@example.com", "reason": "already_exists", "id": "link_001" }],
"failed": [],
"remaining": 0,
"provisioning": "manual",
"summary": { "created": 1, "skipped": 1, "failed": 0 }
}
}Each request attempts up to 500 new assignments. Inspect failed even on HTTP 200 and retry those creators explicitly. When remaining is positive, more unattempted roster members remain; repeat the all-missing request to continue. Invalid selections return HTTP 422 before any writes. MCP exposes the same operation as bulk_create_affiliate_codes.
Performance
GET/v1/affiliates/performance
| Parameter | Type | Description |
|---|---|---|
| creator_email | string | Filter to one creator. |
| date_from / date_to | string | ISO dates; filters activity occurrence time. Date-only values use complete UTC days. |
| page / limit | integer | Standard pagination. |
Verified activity grouped by assignment and currency, with the summary computed from events and ledger adjustments. Date ranges filter event timestamps. Money is in currency minor units; summary.by_currency keeps currencies separate, with current pending, approved, paid and refund adjustment balances.
Commissions
GET/v1/commissions
| Parameter | Type | Description |
|---|---|---|
| status | string | Filter: pending, approved, rejected, paid. |
| creator_email | string | Filter by creator. |
| page / limit | integer | Standard pagination. |
response 200
{
"data": [
{
"id": "evt_001",
"link_id": "link_001",
"creator_email": "emma@example.com",
"campaign_id": null,
"type": "sale",
"source": "shopify",
"amount": 89.99,
"commission": 13.50,
"order_id": "order_9876",
"customer_email": "c***@gmail.com",
"discount_code": "EMMA15",
"affiliate_code": null,
"currency": "USD",
"status": "pending",
"status_updated_at": null,
"status_note": null,
"fraud_flags": null,
"occurred_at": "2026-06-12T18:30:00Z",
"synced_at": "2026-06-12T19:00:00Z"
}
],
"pagination": { "page": 1, "limit": 20, "total": 234, "has_more": true }
}POST/v1/commissions
Reviews commission events: it does not create them (events are recorded by the store integration). Approve, or reject, one at a time or in bulk (max 100 IDs). Approval requires a verified paid order past its review period. Review never erases actual sales; record an allocated external payment to mark commissions paid.
| Field | Type | Description |
|---|---|---|
| status | string | Required: approved or rejected. |
| event_id | string | Single event to update. |
| event_ids | string[] | Bulk update, max 100 per request. |
| note | string | Stored as status_note on each event. |
request: approve two events
curl -X POST "https://api.ugcroster.com/v1/commissions" \
-H "Authorization: Bearer rsk_brand_key" \
-H "Content-Type: application/json" \
-d '{ "event_ids": ["evt_001", "evt_002"], "status": "approved" }'response 200
{ "data": { "updated": 2 } }The /v1/affiliates/commissions tree
An alias over the same canonical order events and transactional review service, with per-event PATCH semantics:
GET/v1/affiliates/commissions
Same filters as /v1/commissions (status, creator_email, pagination); items additionally carry click_id and created_at.
PATCH/v1/affiliates/commissions/{id}
request
curl -X PATCH "https://api.ugcroster.com/v1/affiliates/commissions/comm_001" \
-H "Authorization: Bearer rsk_brand_key" \
-H "Content-Type: application/json" \
-d '{ "status": "rejected", "note": "Duplicate order" }'response 200
{
"data": {
"id": "comm_001",
"status": "rejected",
"status_updated_at": "2026-06-13T15:30:00Z",
"status_note": "Duplicate order"
}
}PATCH/v1/affiliates/commissions/bulk
| Field | Type | Description |
|---|---|---|
| event_ids | string[] | Required, non-empty, max 100 per request. |
| status | string | Required: approved or rejected. |
response 200
{ "data": { "status": "approved", "updated_count": 48, "skipped_count": 2, "total_requested": 50 } }Every selected event must exist and belong to your team. Invalid selections fail before any changes. Identical repeated reviews are skipped; check skipped_count.