This reference lists every /api/v1 endpoint in the AffiliateBase REST API with its parameters, request fields, and response contracts. It is written for developers building an integration. Authentication and permissions are covered in API Keys and REST API.
Global contract
- Auth (one of):
Authorization: Bearer <API_KEY>,Authorization: Basic <base64(API_KEY:)>,X-Api-Key: <API_KEY>. OAuth access tokens issued to AI connectors are refused with403 FORBIDDEN. - 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. An invalid value returns422 VALIDATION_ERROR. - Permissions: read requests (
GET) need thereadaction and all other methods needwrite, for examplev1.referrals.write.
Common error envelope:
{
"error": "Account ID is required",
"code": "MISSING_ACCOUNT_ID"
}Common error codes: MISSING_ACCOUNT_ID, UNAUTHORIZED, FORBIDDEN, NOT_FOUND, VALIDATION_ERROR, INVALID_PARAMETER (400), TOO_MANY_REQUESTS (429; see Rate limits)
Payout endpoints return operation-specific 422 codes: PAYOUT_EXECUTION_FAILED, PAYOUT_RUN_CREATE_FAILED, PAYOUT_RUN_EXECUTION_FAILED, PAYOUT_RUN_REMEDIATION_FAILED, PAYOUT_EXPORT_CREATE_FAILED, PAYOUT_EXPORT_DOWNLOAD_FAILED, PAYOUT_EXPORT_DELETE_FAILED, and PAYOUT_EXPORT_SETTLEMENT_FAILED.
API keys
- Query:
page,limit - Role (session auth):
owneroradmin. API key auth needs a full-access key or exactlyv1.api_keys.manage.
- Query:
- Body
name(string, required)permissions(object, required, non-empty)expires_at(ISO datetime, optional)
- Notes:
permissionsmust be an object.- A request that omits
permissionsor sends an empty object returns422 VALIDATION_ERROR. For full access, send{ "all": true }. - A key authenticated by API key can only create keys whose permissions it already holds.
- Role (session auth):
owneroradmin
- Body
- Revokes key (does not hard-delete row)
- Returns success message JSON
- Role (session auth):
owneroradmin
Affiliates
- Query
page,limitcampaign_idemailstateorstate[](pending|active|disabled|suspicious|rejected|banned)stripe_customer_idupdated_since,updated_until(ISO-8601)expand[](campaign,links,coupon,commission_stats)
- Query
- Body
email(required)campaign_id(recommended; if omitted, an arbitrary non-archived campaign is used (422 if none). Always sendcampaign_id)first_name,last_name(optional)state(optional, defaults toactive)paypal_email,wise_email(optional)
- If the email already belongs to an AffiliateBase user, the request succeeds only when that user is already an affiliate or team member on this account. Otherwise it returns
422; usePOST /api/v1/invitationswithkind=affiliateso the person can accept. - Users created through this endpoint start with an unconfirmed email address.
- Body
- Query:
expand[](campaign,links,coupon,commission_stats)
- Query:
- Body
statecampaign_idpaypal_emailwise_email
statecannot be set tobanned, or changed while the affiliate is banned. Both return422 VALIDATION_ERROR; use the ban and unban endpoints below.
- Body
- Archives by default
- Returns
204 No Content
- Body
reason(required:fraud,fake_traffic,self_referral,tos_violation,brand_abuse,spam,other)note(optional, up to 500 characters; kept for your audit trail, never returned by the API or sent in webhooks)dry_run(boolean, optional; previews the impact without changing anything)idempotency_key(optional; or send theIdempotency-Keyheader)requested_by(optional; who asked for the ban, recorded in the status history)
- Bans every affiliate record of the same person on the account, including archived ones. It voids unpaid commissions (voids are final), removes or reduces payouts that have not been submitted, archives links, and stops promo codes. Payouts already submitted or exported are left as they are and listed in
impact.untouched_payouts. - Returns a slim affiliate view (
id,state,campaign_id,archived,banned_at,ban_reason, without contact or payout details) plusimpact,dry_run, andnoop. Banning someone who is already banned returns200withnoop: trueand an emptyimpact. Retrying with the same idempotency key returns the originalimpactwithout banning again. - Errors:
422 VALIDATION_ERRORfor a missing or unknown reason or a note over 500 characters;404 NOT_FOUNDfor an unknown affiliate. - Permission: a full-access key, or a key with exactly
v1.affiliates.ban. Session auth:owneroradmin.
- Body
- Body
note(required, up to 500 characters)dry_run,idempotency_key,requested_by(optional, as for ban)
- Moves every banned record of the person to
disabled, never straight toactive. Reactivate separately withPATCH /api/v1/affiliates/:id. Voided commissions stay voided, and archived links and stopped promo codes stay stopped. - Returns the same slim affiliate view plus
impact,dry_run, andnoop. Unbanning an affiliate that is not banned returns422 VALIDATION_ERROR. - Permission: same as ban.
- Body
- Affiliate objects include
banned_atandban_reason. Both arenullunlessstateisbanned.
Affiliate coupons
- Returns
204 No Content
- Returns
- Body
force(boolean, optional)
- Body
Campaigns
- Query:
page,limit
- Query:
- Body fields (partial updates supported)
name,slug,urlattribution_model(last_click|first_click; defaults tolast_click)private,private_tokensreward_type(percent|fixed)commission_percentcommission_amount_cents,commission_amount_currencyminimum_payout_cents,minimum_payout_currencymax_commission_period_months,max_commissionsintroductory_commission_percent,introductory_commission_months(percent campaigns; both required together, or both blank to clear)days_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_idpromo_code_provisioning(automatic|individual; defaults toautomatic)default
- Body fields (partial updates supported)
- Archives by default
- Returns
204 No Content
promo_code_provisioning=individual disables future automatic code generation for the campaign. Create or import each affiliate’s chosen code through the promo-code endpoints. Switching modes does not rename, stop, or replace existing codes. Explicit calls to the singular affiliate coupon creation endpoint still create a code.
Links
- Query
affiliate_idcampaign_idpage,limit
- Query
- Body
affiliate_id(required)campaign_id(required)url(required)token(optional; auto-generated if missing)
- Body
- Body:
affiliate_id,campaign_id,url,token
- Body:
- Archives by default
- Returns
204 No Content
Referrals
- Query
page,limitaffiliate_idconversion_stateorconversionStatestripe_customer_idemail(customer email)updated_since,updated_until(ISO-8601)expand[](link,customer,affiliate)
- Query
- 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
- Query:
expand[](link,customer,affiliate)
- Query:
- Body
conversion_state(visitor|lead|conversion)deactivated_at(ISO datetime; deactivates the referral. Sendingnullfor a deactivated referral returns422, because reactivation is not supported)customer_email(optional; binds/creates customer)
- Body
- Soft-deactivates referral
- Returns
204 No Content
Commissions
- Query
page,limitstateorstate[]affiliate_idcampaign_idupdated_since,updated_until(ISO-8601)expand[](campaign,sale)
- Query
- 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
- Body
due_at(ISO datetime, optional)
- Notes:
- Changing
due_atrecalculatespending|due, unless the commission ispaid,processing, orvoided. paid_atis rejected with422 VALIDATION_ERROR. Commissions become paid through payout settlement:POST /api/v1/payouts/:id/payor a payout export payment.- A commission held for fraud review cannot have
due_atchanged (422); resolve it withPOST /api/v1/commissions/:id/review.
- Changing
- Body
- Soft-voids commission
- Body
void_reason(optional)
- Returns
object,id,deleted: false,state,adjustment_commission_id, andpost_submission_adjustment. - If the commission’s payout was already exported, paid, or sent for payment, the commission is left as is and a negative adjustment commission (
adjustment_commission_id,post_submission_adjustment: true) is created to net against the affiliate’s next payout.
- Body
review_action(approve|suspicious|deactivate)
approvereleases the hold and returns the commission topendingordue.suspiciouskeeps it held and suspends the affiliate.deactivatevoids the commission and suspends the affiliate.
- Body
Payouts
- Query
page,limitaffiliate_idstateorstate[]eligible=true(returns eligible payout candidates; non-paginated)updated_since,updated_until(ISO-8601)expand[](affiliate,commissions)
- Query
- Body
payment_reference(optional)dry_run(boolean, optional; previews without paying)idempotency_keyandrequested_by(optional; recorded in the audit trail. TheIdempotency-Keyheader is also accepted)
- If the payout’s method is Stripe, this sends real money through Stripe. PayPal and Wise payouts are recorded as paid; you send the money yourself.
- A Stripe payout that belongs to a payout export is refused with
422. Settle the export instead, or delete it withDELETE /api/v1/payout_exports/:id(Void export before download in the dashboard) if it has not been downloaded.
- Body
Payout exports
Payout export endpoints require the owner or admin role for session auth.
- Query
limit
- Query
- Body
payout_ids(array, optional)export_format(csv|paypal|wise, optional)notes(optional)
- Body
- Query
export_format(csv|paypal|wise, optional)
- Notes:
- Returns metadata plus
filenameandcontent
- Returns metadata plus
- Query
- Body
payment_reference(optional)
- Body
Payout runs
Payout run endpoints require the owner or admin role for session auth.
- Body
idempotency_key(optional; generated if omitted)execute_now(boolean, optional, defaultfalse)affiliate_ids(array, optional)payment_reference(optional; used whenexecute_now=true)
- Body
- Body
async(boolean, optional, defaulttrue)payment_reference(optional)dry_run(boolean, optional; previews without executing)idempotency_key(optional; or send theIdempotency-KeyorX-Idempotency-Keyheader. A key repeated within 24 hours returnsreplayed: truewithout executing again)
- Body
- Body
remediation_action(required)issue_code(optional)payout_ids(array, optional)dry_run,idempotency_key(optional, as for execute)
- Body
- Query
lookback_days(optional, default30)
- Query
Invitations
- Query
kind(member|affiliate, optional)status(pending|accepted|revoked, optional)page,limit
- Query
- Body
kind(member|affiliate, required)email(required)role(formember, optional, defaults tomember)campaign_idorcampaignId(foraffiliate, required)
- Body
- Query
kind(optional but recommended)
- Query
- Body
kind(optional but recommended)invitation_actionorstatus_action(accept|revoke)status=revoked(alias for revoke)role(member-invitation role update path)
- Accepting (
accept) requires a signed-in user whose email matches the invitation, so it works from the dashboard session and not with an API key. An API-key acceptance request returns422, anduser_idis ignored. - Only an account owner can grant the
ownerrole. A full-access API key acts as the owner who created it. A scoped key can never grantowner.
- Body
- Query/body:
kind(optional but recommended)
- Returns
204 No Content
- Query/body:
- Query/body:
kind(optional but recommended)
- Query/body:
LLM and 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"Individually assigned promo codes
Use these endpoints to 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. After an uncertain response, retry with the same key and payload. On OPERATION_PENDING, check the original result. On RECONCILIATION_REQUIRED, review the original operation before another creation attempt. An assignment response does not prove paid attribution.
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 to another affiliate or reactivated after tracking stops. 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 token needs explicit mcp.affiliate_coupons.read / mcp.affiliate_coupons.write permissions. To grant them, select the optional Allow promo-code management checkbox when you create a token. 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.