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
  }
}

GET/v1/affiliates/links

ParameterTypeDescription
creator_emailstringFilter to one creator.
page / limitintegerStandard 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.

FieldTypeDescription
creator_emailstringRequired.
valuestringRequired. The discount code (e.g. "SUMMER20") or the link slug.
typestring"discount_code" (default) or "link".
commission_ratenumberPercentage paid to the creator. Default 0.
campaign_id / creator_namestringOptional campaign and creator metadata; the creator must belong to that authorized roster.
integration_idstringOptional connected store. Existing percentage coupons must be active in that store before import.
hold_days / attribution_daysintegerReview period 0–90 days and attribution window 1–90 days; both default to 30.
destination_urlstringRequired for referral links unless value is an HTTPS destination. Connected offers must use the authorized store host.
currencystringUppercase 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}

FieldTypeDescription
valuestringChange the code or slug.
commission_ratenumberNew rate.
activebooleanEnable or disable the link.
creator_name / platform / campaign_idstring | nullMetadata; campaign_id accepts null to unlink.
url / destination_urlstringLink-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".

FieldTypeDescription
all_missingbooleanSet true to process the roster members missing a code. Use exactly one selector.
creatorsarrayAlternative selector: 1–500 objects with an email matching your roster.
roster_idsstring[]Alternative selector: 1–500 roster record IDs belonging to your team.
campaign_idstringOptional campaign owned by your team; limits the roster to that campaign.
commission_ratenumberCreator commission percentage, 0–100. Default 0; this is not a customer discount.
typestringdiscount_code (default), link, or referral_link (alias for link).
destination_urlstringHTTP(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

ParameterTypeDescription
creator_emailstringFilter to one creator.
date_from / date_tostringISO dates; filters activity occurrence time. Date-only values use complete UTC days.
page / limitintegerStandard 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

ParameterTypeDescription
statusstringFilter: pending, approved, rejected, paid.
creator_emailstringFilter by creator.
page / limitintegerStandard 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.

FieldTypeDescription
statusstringRequired: approved or rejected.
event_idstringSingle event to update.
event_idsstring[]Bulk update, max 100 per request.
notestringStored 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

FieldTypeDescription
event_idsstring[]Required, non-empty, max 100 per request.
statusstringRequired: 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.