Affiliate Management API
Manage affiliates, referral links, and commission configuration for your business programmatically.
Prerequisites
Your API key must be granted the appropriate scopes:
| Scope |
Grants Access To |
affiliates:read |
List and retrieve affiliates, links, commission data |
affiliates:write |
Create, update, delete affiliates and links; manage commission |
Authorization: Bearer <access_token>
Data Models
Affiliate Object
{
"id": 42,
"referral_code": "ABC12345",
"status": "active",
"commission_rate": "10.00",
"notes": "VIP partner",
"approved_at": "2026-04-01T09:00:00.000000Z",
"suspended_at": null,
"terminated_at": null,
"created_at": "2026-03-15T14:22:00.000000Z",
"affiliate_user": {
"id": 7,
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+14155552671"
}
}
| Field |
Type |
Description |
id |
integer |
Unique affiliate ID |
referral_code |
string |
Unique tracking code used in referral links |
status |
string |
pending | active | suspended | terminated |
commission_rate |
string|null |
Affiliate-specific commission rate (%). null = inherits business default |
notes |
string|null |
Internal notes visible only to business owner |
approved_at |
ISO 8601|null |
When the affiliate was approved |
suspended_at |
ISO 8601|null |
When the affiliate was suspended |
terminated_at |
ISO 8601|null |
When the affiliate was terminated |
created_at |
ISO 8601 |
Record creation timestamp |
affiliate_user.id |
integer |
The affiliated user’s account ID |
affiliate_user.name |
string |
Full name |
affiliate_user.email |
string |
Email address |
affiliate_user.phone |
string|null |
Phone number |
Affiliate Status Transitions
pending ──► active ──► suspended ──► active
│ │
▼ ▼
active terminated
│
▼
terminated
| Current Status |
Valid Actions |
pending |
approve, suspend, terminate |
active |
suspend, terminate |
suspended |
reactivate, terminate |
terminated |
(no further transitions) |
Referral Link Object
{
"id": 10,
"affiliate_id": 42,
"slug": "summer2026",
"destination_url": "https://example.com/landing",
"campaign": "Summer Campaign",
"is_active": true,
"click_count": 142,
"tracking_url": "https://yourbusiness.heldsway.com/r/summer2026",
"metadata": { "source": "email" },
"created_at": "2026-04-01T09:00:00.000000Z"
}
| Field |
Type |
Description |
id |
integer |
Unique link ID |
affiliate_id |
integer |
ID of the owning affiliate |
slug |
string |
URL-safe identifier used in the tracking URL |
destination_url |
string |
Where the visitor is sent after click tracking |
campaign |
string|null |
Optional campaign label for grouping |
is_active |
boolean |
Whether this link is currently accepting clicks |
click_count |
integer |
Total recorded clicks |
tracking_url |
string |
The full public URL affiliates share (/r/{slug}) |
metadata |
object|null |
Arbitrary key-value pairs for your own use |
created_at |
ISO 8601 |
Record creation timestamp |
Commission Rule Object
{
"id": 5,
"label": "Black Friday Deal",
"commission_rate": 20.00,
"priority": 10,
"valid_from": "2026-11-28T00:00:00.000000Z",
"valid_until": "2026-11-30T23:59:59.000000Z",
"max_conversions": 100,
"conversion_count": 45,
"is_active": true,
"status": "active",
"created_at": "2026-10-01T09:00:00.000000Z"
}
| Field |
Type |
Description |
id |
integer |
Unique rule ID |
label |
string|null |
Human-readable name for the rule |
commission_rate |
float |
Commission percentage (0–100) |
priority |
integer |
Higher value = higher precedence. When multiple rules apply, the one with the highest priority wins |
valid_from |
ISO 8601|null |
Rule becomes active at this time. null = no start restriction |
valid_until |
ISO 8601|null |
Rule expires at this time. null = no expiry |
max_conversions |
integer|null |
Maximum conversions this rule applies to. null = unlimited |
conversion_count |
integer |
How many conversions have used this rule (read-only) |
is_active |
boolean |
Whether the rule is enabled |
status |
string |
Computed status: active | scheduled | expired | exhausted | disabled |
created_at |
ISO 8601 |
Record creation timestamp |
Batch Object
Returned by the Get Batch Status endpoint after a Bulk Create request.
{
"batch_id": 17,
"status": "completed",
"total_items": 3,
"created_count": 2,
"error_count": 1,
"created_at": "2026-04-14T10:00:00.000000Z",
"completed_at": "2026-04-14T10:00:05.000000Z",
"created_link_ids": [101, 102],
"created_links": [ ... ],
"errors": [ ... ]
}
| Field |
Type |
Description |
batch_id |
integer |
Unique batch ID |
status |
string |
pending | processing | completed | failed |
total_items |
integer |
Number of items submitted in the request |
created_count |
integer |
Number of links successfully created |
error_count |
integer |
Number of items that failed |
created_at |
ISO 8601 |
When the batch was submitted |
completed_at |
ISO 8601|null |
When processing finished. null while pending/processing |
created_link_ids |
array<integer> |
IDs of created links. Present only when completed or failed |
created_links |
array<Referral Link> |
Full link objects with tracking_url. Present only when completed or failed and links exist |
errors |
array |
Per-item errors. Each has index (0-based), destination_url, and message. Present only when completed or failed |
Commission Resolution Order
When a conversion occurs, the system determines the commission rate using this priority chain (highest to lowest):
- Active per-link commission rule (highest priority rule wins)
- Affiliate-level commission rate override
- Business default commission rate
- Platform base rate (fallback)
Quick Reference
Affiliate Endpoints
| Method |
Path |
Scope |
Description |
GET |
/v1/affiliates |
affiliates:read |
List affiliates |
GET |
/v1/affiliates/{id} |
affiliates:read |
Get affiliate |
POST |
/v1/affiliates |
affiliates:write |
Create affiliate (active) |
POST |
/v1/affiliates/register |
affiliates:write |
Affiliate self-registration (pending) |
PATCH |
/v1/affiliates/{id} |
affiliates:write |
Update affiliate |
DELETE |
/v1/affiliates/{id} |
affiliates:write |
Delete affiliate |
POST |
/v1/affiliates/{id}/approve |
affiliates:write |
Approve pending affiliate |
POST |
/v1/affiliates/{id}/suspend |
affiliates:write |
Suspend affiliate |
POST |
/v1/affiliates/{id}/reactivate |
affiliates:write |
Reactivate suspended affiliate |
POST |
/v1/affiliates/{id}/terminate |
affiliates:write |
Terminate affiliate (permanent) |
GET |
/v1/affiliates/stats |
affiliates:read |
Get affiliate stats |
GET |
/v1/affiliates/export |
affiliates:read |
Export affiliates |
GET |
/v1/affiliates/{id}/stats |
affiliates:read |
Get individual affiliate stats |
Referral Link Endpoints
See the dedicated Referral Links page for the canonical endpoint list.
Commission Endpoints
| Method |
Path |
Scope |
Description |
GET |
/v1/affiliates/{id}/commission |
affiliates:read |
Get affiliate commission config |
PUT |
/v1/affiliates/{id}/commission |
affiliates:write |
Set/clear affiliate commission override |
GET |
/v1/links/{id}/commission-rules |
affiliates:read |
List commission rules for link |
POST |
/v1/links/{id}/commission-rules |
affiliates:write |
Create commission rule |
PATCH |
/v1/links/{linkId}/commission-rules/{ruleId} |
affiliates:write |
Update commission rule |
DELETE |
/v1/links/{linkId}/commission-rules/{ruleId} |
affiliates:write |
Delete commission rule |