REST API Endpoint Reference
Reference for currently exposed /api/v1 endpoints.
Global Contract
- Auth (one of):
Authorization: Bearer <API_KEY>,Authorization: Basic <base64(API_KEY:)>,X-Api-Key: <API_KEY> - Account context (required):
?account_id=<ACCOUNT_ID>orX-Account-Id: <ACCOUNT_ID> - Pagination defaults:
page=1,limit=25, maxlimit=100 - Array params:
state[]=due&state[]=pendingorstate=due,pending - Expand params:
expand[]=campaign&expand[]=saleorexpand=campaign,sale - Timestamp filters (
updated_since,updated_until) must be ISO-8601 where supported
Common error envelope:
{
"error": "Account ID is required",
"code": "MISSING_ACCOUNT_ID"
}
Common error codes: MISSING_ACCOUNT_ID, UNAUTHORIZED, FORBIDDEN, NOT_FOUND, VALIDATION_ERROR
Plans
GET /api/v1/plans- Query:
interval(month|monthly|year|annual, optional)
- Response shape:
{ "plans": [...] }
- Query:
Subscription
GET /api/v1/subscription- Response shape:
{ "subscription": { ... } | null, "billing": { ... } }
- Response shape:
PATCH /api/v1/subscription- Body:
plan_id(required for plan changes)billing_interval(optional)billing_cycle_anchor(optional)proration_behavior(optional)
- Body:
POST /api/v1/subscription/cancel- Body:
at_period_end(boolean, optional)
- Body:
POST /api/v1/subscription/pausePOST /api/v1/subscription/resume
API Keys
GET /api/v1/api_keys- Query:
page,limit - Role (session auth):
owneroradmin
- Query:
POST /api/v1/api_keys- Body:
name(string, required)permissions(object, optional)expires_at(ISO datetime, optional)
- Notes:
permissionsmust be an object.- If omitted, key defaults to full access (
{ "all": true }).
- Role (session auth):
owneroradmin
- Body:
DELETE /api/v1/api_keys/:id- Revokes key (does not hard-delete row)
- Returns success message JSON
- Role (session auth):
owneroradmin
Affiliates
GET /api/v1/affiliates- Query:
page,limitcampaign_idemailstateorstate[](pending|active|disabled|suspicious|rejected)stripe_customer_idupdated_since,updated_until(ISO-8601)expand[](campaign,links,coupon,commission_stats)
- Query:
POST /api/v1/affiliates- Body:
email(required)campaign_id(optional if account has an active default campaign)first_name,last_name(optional)state(optional, defaults toactive)paypal_email,wise_email(optional)
- Body:
GET /api/v1/affiliates/:id- Query:
expand[](campaign,links,coupon,commission_stats)
- Query:
PATCH /api/v1/affiliates/:id- Body:
statecampaign_idpaypal_emailwise_email
- Body:
DELETE /api/v1/affiliates/:id- Archives by default
- Returns
204 No Content
Affiliate Coupons
GET /api/v1/affiliates/:affiliate_id/couponPOST /api/v1/affiliates/:affiliate_id/couponPATCH /api/v1/affiliates/:affiliate_id/couponDELETE /api/v1/affiliates/:affiliate_id/coupon- Returns
204 No Content
- Returns
POST /api/v1/affiliates/:affiliate_id/coupon/sync- Body:
force(boolean, optional)
- Body:
Campaigns
GET /api/v1/campaigns- Query:
page,limit
- Query:
POST /api/v1/campaignsPATCH /api/v1/campaigns/:id- Body fields (partial updates supported):
name,slug,urlprivate,private_tokensreward_type(percent|fixed)commission_percentcommission_amount_cents,commission_amount_currencyminimum_payout_cents,minimum_payout_currencymax_commission_period_months,max_commissionsdays_before_referrals_expire,days_until_commissions_are_dueaffiliate_dashboard_text,custom_reward_description,welcome_textcustomers_visible_to_affiliates,sale_description_visible_to_affiliatesparameter_typestripe_coupon_iddefault
- Body fields (partial updates supported):
GET /api/v1/campaigns/:idDELETE /api/v1/campaigns/:id- Archives by default
- Returns
204 No Content
Links
GET /api/v1/links- Query:
affiliate_idcampaign_idpage,limit
- Query:
POST /api/v1/links- Body:
affiliate_id(required)campaign_id(required)url(required)token(optional; auto-generated if missing)
- Body:
GET /api/v1/links/:idPATCH /api/v1/links/:id- Body:
affiliate_id,campaign_id,url,token
- Body:
DELETE /api/v1/links/:id- Archives by default
- Returns
204 No Content
Referrals
GET /api/v1/referrals- Query:
page,limitaffiliate_idconversion_stateorconversionStatestripe_customer_idemail(customer email)updated_since,updated_until(ISO-8601)expand[](link,customer,affiliate)
- Query:
POST /api/v1/referrals- Body:
affiliate_id(required)campaign_id(required whenlink_idis omitted)link_id(optional)conversion_state(visitor|lead|conversion, optional)expires_at(ISO datetime, optional)
- Body:
GET /api/v1/referrals/:id- Query:
expand[](link,customer,affiliate)
- Query:
PATCH /api/v1/referrals/:id- Body:
conversion_state(visitor|lead|conversion)deactivated_at(ISO datetime ornull)customer_email(optional; binds/creates customer)
- Body:
DELETE /api/v1/referrals/:id- Soft-deactivates referral
- Returns
204 No Content
Commissions
GET /api/v1/commissions- Query:
page,limitstateorstate[]affiliate_idcampaign_idupdated_since,updated_until(ISO-8601)expand[](campaign,sale)
- Query:
GET /api/v1/commissions/:idPATCH /api/v1/commissions/:id- Body:
due_at(ISO datetime, optional)paid_at(ISO datetime ornull)
- Notes:
- Setting
paid_atsets state topaid - Clearing
paid_atrecalculatespending|due - Updating paid state for
voidedcommissions is rejected
- Setting
- Body:
DELETE /api/v1/commissions/:id- Soft-voids commission
- Body:
void_reason(optional)
POST /api/v1/commissions/:id/review- Body:
review_action(approve|suspicious|deactivate)
- Body:
Payouts
GET /api/v1/payouts- Query:
page,limitaffiliate_idstateorstate[]eligible=true(returns eligible payout candidates; non-paginated)updated_since,updated_until(ISO-8601)expand[](affiliate,commissions)
- Query:
GET /api/v1/payouts/:idPOST /api/v1/payouts/:id/pay- Body:
payment_reference(optional)
- Body:
Payout Exports
GET /api/v1/payout_exports- Query:
limit
- Query:
POST /api/v1/payout_exports- Body:
payout_ids(array, optional)export_format(csv|paypal|wise, optional)notes(optional)
- Body:
GET /api/v1/payout_exports/:id- Query:
export_format(csv|paypal|wise, optional)
- Notes:
- Returns metadata plus
filenameandcontent
- Returns metadata plus
- Query:
DELETE /api/v1/payout_exports/:idPOST /api/v1/payout_exports/:payout_export_id/payment- Body:
payment_reference(optional)
- Body:
Payout Runs
POST /api/v1/payout_runs- Body:
idempotency_key(optional; generated if omitted)execute_now(boolean, optional, defaultfalse)affiliate_ids(array, optional)payment_reference(optional; used whenexecute_now=true)
- Body:
PUT /api/v1/payout_runs/:id/execute- Body:
async(boolean, optional, defaulttrue)payment_reference(optional)
- Body:
PUT /api/v1/payout_runs/:id/remediate- Body:
remediation_action(required)issue_code(optional)payout_ids(array, optional)
- Body:
GET /api/v1/payout_runs/reconcile- Query:
lookback_days(optional, default30)
- Query:
Invitations
GET /api/v1/invitations- Query:
kind(member|affiliate, optional)status(pending|accepted|revoked, optional)page,limit
- Query:
POST /api/v1/invitations- Body:
kind(member|affiliate, required)email(required)role(formember, optional, defaults tomember)campaign_idorcampaignId(foraffiliate, required)
- Body:
GET /api/v1/invitations/:id- Query:
kind(optional but recommended)
- Query:
PATCH /api/v1/invitations/:id- Body:
kind(optional but recommended)invitation_actionorstatus_action(accept|revoke)status=revoked(alias for revoke)role(member-invitation role update path)user_id(optional for API-key acceptance path)
- Body:
DELETE /api/v1/invitations/:id- Query/body:
kind(optional but recommended)
- Returns
204 No Content
- Query/body:
POST /api/v1/invitations/:id/resend- Query/body:
kind(optional but recommended)
- Query/body:
LLM/SDK Integration Tip
Use the machine-readable contract when generating clients:
- OpenAPI:
/openapi/v1.yaml - Docs page: OpenAPI Spec
Example Request
curl "https://app.affiliatebase.io/api/v1/commissions?account_id=<ACCOUNT_ID>&state=due&expand=campaign,sale&page=1&limit=25" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json"