Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/affiliatebase-io:affiliatebase-io-affiliates-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: AffiliateBase API v1 Affiliates API
version: 1.0.0
description: 'Source-aligned OpenAPI contract for AffiliateBase `/api/v1` endpoints.
Authentication: one of Bearer token, Basic API key auth, or `X-Api-Key`.
Account context: required via `account_id` query param or `X-Account-Id` header.
Write endpoints accept JSON request bodies and Rails-style form-encoded parameters;
responses are JSON encoded. List endpoints use consistent `data` and
`pagination` envelopes.
Rate limits: 45 requests per 30 seconds per credential and 180 per 30 seconds per
IP address, applied before authentication. A throttled request returns HTTP `429`
with error code `TOO_MANY_REQUESTS` and `RateLimit-Limit`, `RateLimit-Remaining`,
`RateLimit-Reset`, and `Retry-After` headers (sent on `429` responses only).
Error codes: `MISSING_ACCOUNT_ID` (400), `INVALID_PARAMETER` (400), `UNAUTHORIZED` (401),
`FORBIDDEN` (403), `NOT_FOUND` (404), `VALIDATION_ERROR` (422), `TOO_MANY_REQUESTS` (429).
Payout endpoints also 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`.'
servers:
- url: https://app.affiliatebase.io
security:
- bearerAuth: []
- basicAuth: []
- apiKeyAuth: []
tags:
- name: Affiliates
paths:
/api/v1/affiliates:
get:
tags:
- Affiliates
operationId: listAffiliates
summary: List affiliates
parameters:
- $ref: '#/components/parameters/AccountIdQuery'
- $ref: '#/components/parameters/AccountIdHeader'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- name: campaign_id
in: query
schema:
type: string
format: uuid
- name: email
in: query
schema:
type: string
format: email
- name: state
in: query
schema:
$ref: '#/components/schemas/AffiliateState'
- name: state[]
in: query
schema:
type: array
items:
$ref: '#/components/schemas/AffiliateState'
- name: stripe_customer_id
in: query
schema:
type: string
- name: updated_since
in: query
schema:
type: string
format: date-time
- name: updated_until
in: query
schema:
type: string
format: date-time
- $ref: '#/components/parameters/Expand'
- $ref: '#/components/parameters/ExpandBracket'
responses:
'200':
description: Paginated affiliate list
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedAffiliates'
'400':
$ref: '#/components/responses/MissingAccountId'
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/TooManyRequests'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/ValidationError'
post:
tags:
- Affiliates
operationId: createAffiliate
summary: Create affiliate
description: 'If the email belongs to an existing user, the request succeeds only when that
user is already an affiliate or team member on this account. Otherwise it returns
`422`; use `POST /api/v1/invitations` with `kind=affiliate` instead. Users created
here start with an unconfirmed email address.'
parameters:
- $ref: '#/components/parameters/AccountIdQuery'
- $ref: '#/components/parameters/AccountIdHeader'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- email
properties:
email:
type: string
format: email
campaign_id:
type: string
format: uuid
description: Recommended. If omitted, an arbitrary non-archived campaign is used; always send `campaign_id`.
first_name:
type: string
last_name:
type: string
state:
type: string
paypal_email:
type: string
format: email
wise_email:
type: string
format: email
application/x-www-form-urlencoded:
schema:
type: object
required:
- email
properties:
email:
type: string
format: email
campaign_id:
type: string
format: uuid
first_name:
type: string
last_name:
type: string
state:
type: string
paypal_email:
type: string
format: email
wise_email:
type: string
format: email
responses:
'201':
description: Affiliate created
content:
application/json:
schema:
$ref: '#/components/schemas/Affiliate'
'400':
$ref: '#/components/responses/MissingAccountId'
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/TooManyRequests'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/ValidationError'
/api/v1/affiliates/{id}:
get:
tags:
- Affiliates
operationId: getAffiliate
summary: Get affiliate
parameters:
- $ref: '#/components/parameters/AccountIdQuery'
- $ref: '#/components/parameters/AccountIdHeader'
- $ref: '#/components/parameters/Id'
- $ref: '#/components/parameters/Expand'
- $ref: '#/components/parameters/ExpandBracket'
responses:
'200':
description: Affiliate payload
content:
application/json:
schema:
$ref: '#/components/schemas/Affiliate'
'400':
$ref: '#/components/responses/MissingAccountId'
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/TooManyRequests'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
patch:
tags:
- Affiliates
operationId: updateAffiliate
summary: Update affiliate
description: '`state` cannot be set to `banned`, and cannot change while the affiliate is banned;
both return `422 VALIDATION_ERROR`. Use `POST /api/v1/affiliates/{id}/ban` and
`POST /api/v1/affiliates/{id}/unban` instead.'
parameters:
- $ref: '#/components/parameters/AccountIdQuery'
- $ref: '#/components/parameters/AccountIdHeader'
- $ref: '#/components/parameters/Id'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
state:
type: string
campaign_id:
type: string
format: uuid
paypal_email:
type: string
format: email
wise_email:
type: string
format: email
responses:
'200':
description: Updated affiliate payload
content:
application/json:
schema:
$ref: '#/components/schemas/Affiliate'
'400':
$ref: '#/components/responses/MissingAccountId'
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/TooManyRequests'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
delete:
tags:
- Affiliates
operationId: deleteAffiliate
summary: Archive affiliate
parameters:
- $ref: '#/components/parameters/AccountIdQuery'
- $ref: '#/components/parameters/AccountIdHeader'
- $ref: '#/components/parameters/Id'
responses:
'204':
description: Affiliate archived/deleted
'400':
$ref: '#/components/responses/MissingAccountId'
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/TooManyRequests'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
/api/v1/affiliates/{id}/ban:
post:
tags:
- Affiliates
operationId: banAffiliate
summary: Ban affiliate
description: 'Bans the affiliate for misconduct. The ban applies to every affiliate record of the
same person on the account (kept and archived, any campaign); `id` may be any of
them. In one transaction it voids unpaid (`pending` and `due`, and `processing` on
payouts not yet submitted or exported) commissions, removes or resizes unsubmitted
payouts, archives links, and stops promo codes. Payouts already submitted or exported
are left unchanged and listed in `impact.untouched_payouts`. Voids are final.
Requires a full-access key or a key that holds exactly `v1.affiliates.ban`. Full access
means `all` or `*`. Broad permissions such as `write`, `v1.affiliates.write`, and scoped
wildcards such as `v1.*` do not grant it. The response is a slim affiliate view without
contact or payout details.
Session callers must be owners or admins.
Send `dry_run: true` to preview the impact without writing. Reuse the same
`Idempotency-Key` (or `idempotency_key`) after a timeout: while the ban is in effect,
the original impact is returned and nothing is written again. Banning a person who is
already banned returns `200` with `noop: true` and an empty `impact`. Publishes
`affiliate.banned` once per banned record.'
parameters:
- $ref: '#/components/parameters/AccountIdQuery'
- $ref: '#/components/parameters/AccountIdHeader'
- $ref: '#/components/parameters/Id'
- $ref: '#/components/parameters/IdempotencyKeyHeader'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AffiliateBanRequest'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/AffiliateBanRequest'
responses:
'200':
description: Ban executed, previewed (`dry_run`), replayed, or a no-op for an already banned person
content:
application/json:
schema:
$ref: '#/components/schemas/AffiliateBanResult'
'400':
$ref: '#/components/responses/MissingAccountId'
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/TooManyRequests'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
description: Missing or unknown reason, note over 500 characters, invalid `dry_run`, or an idempotency key whose ban was since lifted
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: A ban reason is required.
code: VALIDATION_ERROR
/api/v1/affiliates/{id}/unban:
post:
tags:
- Affiliates
operationId: unbanAffiliate
summary: Unban affiliate
description: 'Lifts the ban on every banned affiliate record of the person and moves them to
`disabled`, never straight to `active`; reactivate separately with
`PATCH /api/v1/affiliates/{id}`. Voided commissions stay voided, archived links stay
archived, and stopped promo codes stay stopped. Requires the same `v1.affiliates.ban`
permission as the ban. Supports `dry_run` and `Idempotency-Key`. Publishes
`affiliate.unbanned` once per record.'
parameters:
- $ref: '#/components/parameters/AccountIdQuery'
- $ref: '#/components/parameters/AccountIdHeader'
- $ref: '#/components/parameters/Id'
- $ref: '#/components/parameters/IdempotencyKeyHeader'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AffiliateUnbanRequest'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/AffiliateUnbanRequest'
responses:
'200':
description: Unban executed, previewed (`dry_run`), or replayed
content:
application/json:
schema:
$ref: '#/components/schemas/AffiliateUnbanResult'
'400':
$ref: '#/components/responses/MissingAccountId'
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/TooManyRequests'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
description: Missing note, note over 500 characters, affiliate not banned, invalid `dry_run`, or an idempotency key whose unban was followed by a new ban
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: A note explaining the unban is required.
code: VALIDATION_ERROR
components:
schemas:
Error:
type: object
required:
- error
- code
properties:
error:
type: string
code:
type: string
details:
oneOf:
- type: 'null'
- type: object
additionalProperties: true
- type: array
items:
type: string
AffiliateBanImpact:
type: object
description: What the ban did (or, with `dry_run`, would do), combined across the person's records. Empty when `noop` is true.
properties:
voided_commissions:
type: array
items:
type: object
properties:
id:
type: string
format: uuid
amount_cents:
type: integer
currency:
type: string
state:
type: string
voided_totals:
type: object
description: Voided amount in cents per currency code.
additionalProperties:
type: integer
payouts_resized:
type: array
items:
type: string
format: uuid
payouts_removed:
type: array
items:
type: string
format: uuid
untouched_payouts:
type: array
description: Submitted or exported payouts left unchanged, because money may already have left.
items:
type: object
properties:
id:
type: string
format: uuid
state:
type: string
amount_cents:
type: integer
currency:
type: string
reason:
type: string
enum:
- submitted
- exported
links_archived:
type: integer
codes_stopped:
type: integer
affiliates:
type: array
description: One row per affiliate record of the person that the ban applies to.
items:
type: object
additionalProperties: true
properties:
id:
type: string
format: uuid
campaign_id:
type: string
format: uuid
campaign_name:
type: string
archived:
type: boolean
AffiliateUnbanResult:
allOf:
- $ref: '#/components/schemas/AffiliateBanSubject'
- type: object
required:
- impact
- dry_run
- noop
properties:
impact:
type: object
properties:
from_state:
type: string
enum:
- banned
to_state:
type: string
enum:
- disabled
affiliates:
type: array
items:
type: object
additionalProperties: true
dry_run:
type: boolean
noop:
type: boolean
Pagination:
type: object
required:
- previous_page
- current_page
- next_page
- count
- limit
- total_pages
- total_count
properties:
previous_page:
oneOf:
- type: integer
- type: 'null'
current_page:
type: integer
next_page:
oneOf:
- type: integer
- type: 'null'
count:
type: integer
limit:
type: integer
total_pages:
type: integer
total_count:
type: integer
AffiliateState:
type: string
enum:
- pending
- active
- disabled
- suspicious
- rejected
- banned
description: '`banned` is entered and left only through the ban and unban endpoints.
'
AffiliateBanReason:
type: string
enum:
- fraud
- fake_traffic
- self_referral
- tos_violation
- brand_abuse
- spam
- other
AffiliateBanRequest:
type: object
required:
- reason
properties:
reason:
$ref: '#/components/schemas/AffiliateBanReason'
note:
type: string
maxLength: 500
description: Internal note for the audit trail. Never returned by the API or sent in webhooks.
dry_run:
type: boolean
default: false
idempotency_key:
type: string
description: Alternative to the `Idempotency-Key` header.
requested_by:
type: string
maxLength: 255
description: Who asked for the ban, for the audit trail. Defaults to the API key name or the signed-in user's email.
AffiliateBanResult:
allOf:
- $ref: '#/components/schemas/AffiliateBanSubject'
- type: object
required:
- impact
- dry_run
- noop
properties:
impact:
$ref: '#/components/schemas/AffiliateBanImpact'
dry_run:
type: boolean
noop:
type: boolean
description: True when every record of the person was already banned.
AffiliateUnbanRequest:
type: object
required:
- note
properties:
note:
type: string
minLength: 1
maxLength: 500
dry_run:
type: boolean
default: false
idempotency_key:
type: string
description: Alternative to the `Idempotency-Key` header.
requested_by:
type: string
maxLength: 255
Affiliate:
type: object
properties:
id:
type: string
format: uuid
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
email:
type: string
first_name:
type: string
last_name:
type: string
state:
$ref: '#/components/schemas/AffiliateState'
banned_at:
type:
- string
- 'null'
format: date-time
description: When the affiliate was banned; `null` unless `state` is `banned`.
ban_reason:
oneOf:
- $ref: '#/components/schemas/AffiliateBanReason'
- type: 'null'
description: The ban reason; `null` unless `state` is `banned`.
paypal_email:
type: string
wise_email:
type: string
PaginatedAffiliates:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Affiliate'
pagination:
$ref: '#/components/schemas/Pagination'
AffiliateBanSubject:
type: object
description: A deliberately slim view of the affiliate. The ban permission lets a key ban an affiliate, not read their contact or payout details.
required:
- id
- state
- campaign_id
- archived
- banned_at
- ban_reason
properties:
id:
type: string
format: uuid
state:
$ref: '#/components/schemas/AffiliateState'
campaign_id:
type: string
format: uuid
archived:
type: boolean
banned_at:
type:
- string
- 'null'
format: date-time
description: When the ban took effect; `null` unless `state` is `banned`.
ban_reason:
type:
- string
- 'null'
description: The ban reason; `null` unless `state` is `banned`.
parameters:
Id:
name: id
in: path
required: true
schema:
type: string
format: uuid
Page:
name: page
in: query
schema:
type: integer
minimum: 1
IdempotencyKeyHeader:
name: Idempotency-Key
in: header
required: false
description: Stable key for this operation. A retry with the same key returns the original result without writing again. `X-Idempotency-Key` is also accepted.
schema:
type: string
Expand:
name: expand
in: query
schema:
type: string
description: Comma-delimited expand list.
AccountIdHeader:
name: X-Account-Id
in: header
required: false
schema:
type: string
format: uuid
description: Account context header. Required unless `account_id` query param is supplied.
AccountIdQuery:
name: account_id
in: query
required: false
schema:
type: string
format: uuid
description: Account context. Required unless `X-Account-Id` is supplied.
ExpandBracket:
name: expand[]
in: query
schema:
type: array
items:
type: string
Limit:
name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
responses:
TooManyRequests:
description: API rate limit exceeded
headers:
RateLimit-Limit:
schema:
type: integer
description: Maximum requests allowed in the current window.
RateLimit-Remaining:
schema:
type: integer
description: Requests remaining in the current window.
RateLimit-Reset:
schema:
type: integer
description: Seconds until the current rate limit window resets.
Retry-After:
schema:
type: integer
description: Seconds to wait before retrying.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: Too many API requests. Please retry shortly.
code: TOO_MANY_REQUESTS
NotFound:
description: Resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: Not found
code: NOT_FOUND
Unauthorized:
description: Authentication failed
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: Invalid API Secret.
code: UNAUTHORIZED
Forbidden:
description: Authenticated but not authorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: Forbidden
code: FORBIDDEN
ValidationError:
description: Validation or state-transition error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: Validation failed
code: VALIDATION_ERROR
MissingAccountId:
description: Missing account context
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: Account ID is required
code: MISSING_ACCOUNT_ID
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: API Key
basicAuth:
type: http
scheme: basic
apiKeyAuth:
type: apiKey
in: header
name: X-Api-Key