Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: distribution Audience API
version: 1.29.0
description: 'Your own distribution workspace for your agents and systems. Every endpoint takes an API key you create in the workspace (Developers) as Authorization: Bearer and returns exactly what the workspace shows you. Reads are GET. The writes (start a campaign, change its creators, set what its creators read, approve for a payment link) need a key with campaigns:write or plans:approve, an Idempotency-Key header, and act only inside the mandate your brand sets on the key in Developers: its maximum plan total, monthly cap, channels, whether it may sign, its expiry and the brand terms a person accepted for it. A request outside the mandate is refused before any spend with the limit and how much over. Approved creators on sale are listed by name with their X handle and profile link, before any purchase, and every creator on a plan line is named before payment; a creator who is not approved carries no handle in lists and profiles; not-reviewed, declined and paused creators are never listed (operator decisions 2026-10-08). What bookable means (DT-021): A creator is bookable (on sale) when all of these hold: our team approved the creator after review (verified and active); our review keeps the creator among those we sell, not flagged as an inactive account and not excluded; and at least one of the creator''s formats has a fresh price: a price at most 30 days old, or a price quoted by our team. Every surface counts bookable creators with this one rule (the Creators list''s priced, Market''s Bookable now, the Overview, the chat, creators_search priced and catalog.priced, GET /api/network/facts and the guest quote), so the same filter shows the same number. An approved creator who is not bookable is still listed, with price on request. Any valid key may send feedback (POST /feedback) when something fails, is missing or could be better; it reaches the team directly. The same reads and writes are tools on the MCP server at /api/mcp. Changelog: 2026-10-21 (1.29.0): a quote line carries review, the creator''s review state (Approved, Under review), on REST and MCP; vetting stays as a deprecated alias with the same value until 2026-11-20, so read review (DT-205). 2026-10-21 (1.28.0): every approved creator is named before purchase: its X handle and profile link (handle, url) on every creator read, GET /creators rows and creators_search (CreatorSummary now lists handle and url), GET /creators/{id} and creator_get, with its post links; and a plan names its creators before payment too: plan_quote lines carry creator.handle and creator.profile_url, and campaign_status line slots carry the @handle, whatever the order''s payment state. A creator who is not approved carries no handle in lists and profiles. 2026-10-21 (1.27.0): every campaign (list and status) and every line proposal carries brand_context_version, the version of your brand context (GET /brain) in force when it was created; it is frozen there, so editing the context later never changes it, and null means there was no context yet. 2026-10-21 (1.26.3): GET /creators and GET /creators/{id} refuse a query parameter they do not take (handle, for one) with 400 bad_request, details.problems naming it and details.accepted listing what they take, instead of ignoring it. A client that sends an extra parameter now gets 400 and must drop it. Over the daily creator-view limit, an id not opened today answers 429 daily_seen before it is looked up, so an id no creator has answers 429 too, not 404: the limit never reveals which ids exist (DT-324). 2026-10-21 (1.26.2): a creator read''s 429 daily_lists (the day''s 60 list calls, each GET /creators page or creators_search) and daily_reveals carry details.limit, and daily_lists says list calls, never creator views; both are described with the creator read limits (DT-337).'
servers:
- url: https://app.distribution.tech/api/v1
tags:
- name: Audience
paths:
/audience:
get:
summary: Audience fit for one of your campaigns, or for a profile
description: 'Scope: audience:read.'
security:
- apiKey:
- audience:read
parameters:
- name: intent_id
in: query
required: false
description: One of your campaigns. Or leave out and send a profile.
schema:
type: string
format: uuid
- name: product
in: query
required: false
schema:
type: string
maxLength: 500
- name: audience
in: query
required: false
schema:
type: string
maxLength: 500
- name: geography
in: query
required: false
schema:
type: string
maxLength: 200
responses:
'200':
description: OK
headers:
RateLimit-Limit:
description: Requests one window allows for this key.
schema:
type: integer
RateLimit-Remaining:
description: Requests left in the current window.
schema:
type: integer
RateLimit-Reset:
description: Seconds until the current window closes; the next request after that opens a new one.
schema:
type: integer
RateLimit-Policy:
description: 'The limit and the window in seconds, e.g. 60;w=60. The window is fixed: it opens at the key''s first request after the last one closed (DT-271), so a burst across two windows can pass more than the limit in one rolling minute.'
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/AudienceFit'
'400':
description: 'A parameter is not valid: details.problems names each field and what it accepts.'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: No API key, an unknown one, or a revoked one.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: The key does not have this endpoint's scope.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: No campaign of yours has that id.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: 'Too many requests for this key in the current minute (60); Retry-After and RateLimit-Reset say when to try again. On POST /campaigns and on POST /plans/current/lines when it starts a plan: the brand''s 3 new campaigns in 24 hours are used (details.reason daily_campaign_limit); details.resets_at and Retry-After say when the limit reopens, a rolling 24 hours from the first of them, not a calendar day; archiving or deleting a campaign does not give its slot back. On GET /creators and GET /creators/{id}: a creator read limit is used (details.reason per_minute, daily_lists, daily_reveals, daily_seen or locked). daily_seen is your workspace''s one pool of 300 creator views a day (300 different creators shown or opened since midnight UTC), shared by the app and every API key of the brand: details.scope workspace and details.limit 300; a creator already seen today, in the app or through any key, still opens and costs nothing. daily_lists is the day''s list calls (each GET /creators page or creators_search is one; details.limit, 60): it is counted apart from creator views, resets at midnight UTC, and Retry-After says when. daily_reveals is the day''s creator profiles opened (details.limit, 60). The other reasons are this key''s own limit (details.scope key) or the brand''s ceiling over all its keys (details.scope api).'
headers:
Retry-After:
schema:
type: integer
RateLimit-Limit:
description: Requests one window allows for this key.
schema:
type: integer
RateLimit-Remaining:
description: Requests left in the current window.
schema:
type: integer
RateLimit-Reset:
description: Seconds until the current window closes; the next request after that opens a new one.
schema:
type: integer
RateLimit-Policy:
description: 'The limit and the window in seconds, e.g. 60;w=60. The window is fixed: it opens at the key''s first request after the last one closed (DT-271), so a burst across two windows can pass more than the limit in one rolling minute.'
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: 'internal: the request failed on our side. Try again.'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: 'unavailable: the service or this part of it is not reachable right now. Try again shortly.'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
tags:
- Audience
operationId: getAudience
x-operation-id-source: derived
components:
schemas:
Segment:
type: object
properties:
id:
type: string
label:
type: string
required:
- id
- label
additionalProperties: false
Error:
type: object
properties:
error:
type: object
properties:
code:
type: string
enum:
- bad_request
- filter_required
- unauthorized
- forbidden
- not_found
- method_not_allowed
- rate_limited
- unavailable
- internal
- mandate_refused
- conflict
- unprocessable
- idempotency_conflict
- in_progress
message:
type: string
details:
type: object
description: 'Machine-readable facts. mandate_refused: reason (no_mandate, mandate_expired, channel_not_allowed, approval_not_allowed, terms_not_accepted, over_max_plan_total, over_monthly_cap, over_budget), limit_cents, requested_cents, over_by_cents, spent_cents, and escalate: true (take it to a person at the brand). conflict: reason; for over_budget on plan_add_creator or plan_swap_creator also budget_cents, remaining_cents (the room the plan had before the creator), price_cents and over_by_cents. unprocessable: problems, each a field and a message.'
required:
- code
- message
additionalProperties: false
required:
- error
additionalProperties: false
ChannelFit:
type: object
properties:
channel:
type: string
enum:
- x_creators
- reddit
- clipping
label:
type: string
sale:
type: string
enum:
- live
- next
level:
type: string
enum:
- strong
- thin
- none
verified_nodes:
type: integer
description: Approved creators (or communities, clippers) that reach the audience. For x_creators, the creator list's own total for that audience (creators_search total).
bookable_nodes:
type: integer
description: 'Of those, the creators bookable now by the one bookable rule: the same count as creators_search priced and catalog.priced for the same audience, never above the network''s.'
priced_units:
type: integer
description: 'Their posts on sale at a current price: a count of posts, not creators. Bookable creators are counted by creators_search priced and catalog.priced.'
note:
type: string
required:
- channel
- label
- sale
- level
- verified_nodes
- bookable_nodes
- priced_units
- note
additionalProperties: false
AudienceFit:
type: object
properties:
version:
const: 1
computed_at:
type: string
format: date-time
coverage_as_of:
type:
- string
- 'null'
format: date-time
segments:
type: array
items:
$ref: '#/components/schemas/Segment'
regions:
type: array
items:
type: string
unresolved:
type: boolean
channels:
type: array
items:
$ref: '#/components/schemas/ChannelFit'
thin:
type: boolean
summary:
type: string
required:
- version
- computed_at
- coverage_as_of
- segments
- regions
- unresolved
- channels
- thin
- summary
additionalProperties: false
securitySchemes:
apiKey:
type: http
scheme: bearer
description: 'An API key from the workspace. Scopes: inventory:read (Network coverage for your audience), audience:read (Audience fit for a campaign or a profile), campaigns:read (Campaigns and where each stands), evidence:read (Proof of each paid post), results:read (Results of each paid post), brain:read (Your company context), creators:read (Approved creators on sale, by name, with price per format), campaigns:write (Start campaigns and change the creators on a plan, within its mandate), plans:approve (Sign a plan and get its payment link, within its mandate). Rate limit: 60 requests a minute per key.'