Use this reference to choose the current /api/v1 endpoint, parameters, and response contract for an AffiliateBase integration.
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
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/:id- Returns the commission object directly, not wrapped in
data. - Includes expanded
campaignandsaledata. - The expanded sale includes referral, customer, and affiliate details when present.
- Common enrichment fields:
sale.referral.customer.emailsale.referral.customer.namesale.referral.stripe_customer_idsale.affiliate.idsale.affiliate.emailsale.affiliate.first_namesale.affiliate.last_name
- Returns the commission object directly, not wrapped in
PATCH /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"
Related Guides
Individually assigned promo codes
These endpoints let you manage individually assigned Stripe promo codes. Stripe operations require a connected Stripe account and an active affiliate in an active campaign. They use the existing v1.affiliate_coupons.read and v1.affiliate_coupons.write API permissions.
| Endpoint | Behavior |
|---|---|
GET /api/v1/affiliates/:affiliate_id/promo_codes | List assignments; use q for exact Stripe code search or discounts=true for valid discounts. |
POST /api/v1/affiliates/:affiliate_id/promo_codes | Preview/import an exact stripe_promotion_code_id, or use mode=create, code and stripe_coupon_id. |
PATCH /api/v1/affiliates/:affiliate_id/promo_codes/:id | Preview or persist the current provider observation. |
DELETE /api/v1/affiliates/:affiliate_id/promo_codes/:id | Preview or stop tracking locally, keeping Stripe redemption and historical records intact. |
Writes default to dry_run=true. Execute using dry_run=false; import and creation also require a stable Idempotency-Key. Reuse that key with the same payload after an uncertain response. OPERATION_PENDING requires checking the original result; RECONCILIATION_REQUIRED requires review before another creation attempt. An assignment response is not paid-attribution proof.
Display code to customers. tracking_token is an opaque compatibility identifier. Ownership uses the exact provider ID, account and live/test mode. Codes cannot be transferred or reactivated through this release. The existing singular /coupon endpoint remains the legacy campaign default.
The affiliate_promo_codes MCP tool exposes the same operations and defaults to preview. A connector needs explicit mcp.affiliate_coupons.read / mcp.affiliate_coupons.write permissions. New connector creation offers an optional Allow promo-code management checkbox; existing tokens keep their current permissions.
See Manage Promo Codes with MCP for copyable tool calls, permission setup and retry guidance, or Assign Stripe Promo Codes to Affiliates for the merchant workflow.