--- title: "Run a campaign with your agent | distribution.tech" description: "How an agent runs a distribution campaign with an API key: the eight-step flow, the limits, the spending mandate, every error code and feedback." canonical: https://distribution.tech/docs/agents generator: md-live-route generated: 2026-10-21T10:52:14.793Z --- # Run a campaign with your agent | distribution.tech - [Getting started](https://distribution.tech/docs) - [API reference](https://distribution.tech/docs/api) - [MCP and agents](https://distribution.tech/docs/agents) - [Changelog](https://distribution.tech/docs/changelog) Search the docs Docs - Agents › - [Run a campaign with your agent](https://distribution.tech/docs/agents) - [MCP server](https://distribution.tech/docs/mcp) - MCP tools › - [inventory](https://distribution.tech/docs/mcp/tools/inventory) - [resolve\_audience](https://distribution.tech/docs/mcp/tools/resolve-audience) - [campaign\_status](https://distribution.tech/docs/mcp/tools/campaign-status) - [evidence](https://distribution.tech/docs/mcp/tools/evidence) - [results](https://distribution.tech/docs/mcp/tools/results) - [brain\_get](https://distribution.tech/docs/mcp/tools/brain-get) - [creators\_search](https://distribution.tech/docs/mcp/tools/creators-search) - [creator\_get](https://distribution.tech/docs/mcp/tools/creator-get) - [creator\_ask\_price](https://distribution.tech/docs/mcp/tools/creator-ask-price) - [plan\_quote](https://distribution.tech/docs/mcp/tools/plan-quote) - [create\_campaign](https://distribution.tech/docs/mcp/tools/create-campaign) - [plan\_add\_creator](https://distribution.tech/docs/mcp/tools/plan-add-creator) - [plan\_remove\_creator](https://distribution.tech/docs/mcp/tools/plan-remove-creator) - [plan\_move\_dates](https://distribution.tech/docs/mcp/tools/plan-move-dates) - [plan\_swap\_creator](https://distribution.tech/docs/mcp/tools/plan-swap-creator) - [set\_creator\_guidelines](https://distribution.tech/docs/mcp/tools/set-creator-guidelines) - [approve\_plan](https://distribution.tech/docs/mcp/tools/approve-plan) - [archive\_campaign](https://distribution.tech/docs/mcp/tools/archive-campaign) - [rename\_campaign](https://distribution.tech/docs/mcp/tools/rename-campaign) - [delete\_campaign](https://distribution.tech/docs/mcp/tools/delete-campaign) - [feedback\_send](https://distribution.tech/docs/mcp/tools/feedback-send) - [feedback\_list](https://distribution.tech/docs/mcp/tools/feedback-list) 1. [distribution](https://distribution.tech/) 2. / [Docs](https://distribution.tech/docs) 3. / Run a campaign with your agent MCP and agents # Run a campaign with your agent This guide gives you everything an agent needs to run a distribution campaign with an API key: the eight-step flow, the request and campaign limits, the spending mandate that caps what a key can spend, every error code and what to do on the common refusals, and how to send feedback. Copy page as markdown [View .md](https://distribution.tech/docs/agents.md) Per our API limits, one key makes up to 60 requests a minute and one brand starts up to 3 new campaigns a day. The machine-readable contract is [openapi.json](https://distribution.tech/openapi.json). Keys and mandates are set in the workspace under Developers. What changed in the API and the app each week is in the [changelog](https://distribution.tech/changelog). ## Connect your agent Approved brands only. We review every brand before its agent can buy. Sign in at [Connect your agent](https://app.distribution.tech/connect) to ask for approval; once your brand is approved, that page gives you the MCP link to copy, and you create a key in [Developers](https://app.distribution.tech/workspace/developers). New to distribution? [Connect an agent](https://distribution.tech/distribution#access) to ask for access. ### Before you have a key: the guest server The guest server is `https://app.distribution.tech/api/mcp/guest`, with no key and no sign-in. Your agent can add it and list its tools now. With no key it answers how much of the network is on sale per channel, the fit for an audience you describe, the all-in price range per post and that range times the posts you name, and what the connection can do before you have a key. Anything that touches a campaign of yours needs an approved brand and a key. In Cursor: [add the guest server in one click](cursor://anysphere.cursor-deeplink/mcp/install?name=distribution&config=eyJ1cmwiOiJodHRwczovL2FwcC5kaXN0cmlidXRpb24udGVjaC9hcGkvbWNwL2d1ZXN0In0=). The link opens Cursor and adds it to your MCP servers as `distribution`. #### Codex, in ~/.codex/config.toml ``` [mcp_servers.distribution] url = "https://app.distribution.tech/api/mcp/guest" ``` #### Claude Code, in a terminal ``` claude mcp add --transport http distribution https://app.distribution.tech/api/mcp/guest ``` ### With your key The MCP server is `https://app.distribution.tech/api/mcp` (streamable HTTP). Send your API key from Developers as `Authorization: Bearer` plus the key. #### Claude Code, in a terminal ``` claude mcp add --transport http distribution https://app.distribution.tech/api/mcp --header "Authorization: Bearer YOUR_API_KEY" ``` #### Cursor, in ~/.cursor/mcp.json ``` { "mcpServers": { "distribution": { "url": "https://app.distribution.tech/api/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } ``` #### Codex, in ~/.codex/config.toml ``` [mcp_servers.distribution] url = "https://app.distribution.tech/api/mcp" bearer_token_env_var = "DISTRIBUTION_API_KEY" # then, in the shell that starts Codex: export DISTRIBUTION_API_KEY=YOUR_API_KEY ``` ## Three recipes ### Where does my campaign stand? Ask your agent: “Check my latest distribution campaign and tell me what is live and what is next.” 1. campaign\_status for the campaign: its stage and each placement's state. 2. results for the numbers the posts have earned so far. ### Quote and approve the plan Ask your agent: “Quote my draft plan, and if my key's mandate allows it, approve it and give me the pay link.” 1. campaign\_status without campaign\_id lists your campaigns with their campaign\_id; campaign\_status with it returns the current plan, whose id (plan.id) the next two steps take. 2. plan\_quote for that plan.id: the plan as signed, its terms\_fingerprint, and whether the mandate allows signing now. 3. approve\_plan for that plan.id with the terms\_fingerprint and an idempotency\_key: signs the plan and returns the checkout link. ### Show me the proof Ask your agent: “List the proof for every post in my campaign, with links.” 1. evidence for the campaign: each post's live link and its delivery proof. Your agent reads and writes your distribution workspace with an API key from Developers. The key's scopes decide which tools it sees, and its mandate decides what it may spend. ## The flow 1. brain\_get: your company context, so the campaign speaks for the right product and audience. 2. resolve\_audience: which audience segments and channels your audience matches, and how strong coverage is. 3. creators\_search with match set to those segments: the recommended approved creators, each with an all-in price per format. creator\_get for one creator's full profile. 4. create\_campaign: from a goal (launch, funding, feature or program), a product, a moment, a window and a budget to a priced plan, or a plan\_note when nothing on sale fits yet. Audience and company come from your company context when left out, the markets default to worldwide and the outcome to the goal's usual one; the answer's defaults names each. With no budget\_min\_usd the budget is held to the key's mandate. 5. plan\_add\_creator and plan\_remove\_creator to change the plan, or plan\_swap\_creator to replace one creator with another in one step; set\_creator\_guidelines for what the booked creators read. 6. plan\_quote: the plan as you sign it, the terms\_fingerprint, and whether the key's mandate allows signing it now. 7. approve\_plan with that terms\_fingerprint: signs the plan and returns the Stripe Checkout link the brand pays. 8. campaign\_status, evidence and results: where it stands, proof of each post, and the numbers. archive\_campaign takes a campaign out of the list; delete\_campaign removes a draft that was never sent. ## Limits - 60 requests per key in a fixed 60-second window, which opens at the key's first request after the last window closed; RateLimit-Remaining and RateLimit-Reset count down that window. Over it you get 429 rate\_limited with Retry-After. A burst that runs across two windows can pass more than 60 in one rolling minute, so pace by the headers, not by your own clock. - 3 new campaigns in any 24 hours per brand, counting a plan plan\_add\_creator starts; archiving or deleting one does not give its slot back. Over it you get 429 rate\_limited with details.reason daily\_campaign\_limit, and details.resets\_at (Retry-After in seconds) is when the limit reopens: 24 hours after the first of them, not midnight. - creators\_search lists the approved creators that reach an audience whenever one applies: the list is the segments you pass in match, else your brand's own audience (the same creators inventory counts); a segment you name without match replaces your audience as the filter; q, reach\_band and the filters narrow it. With no brand audience on file, a call that names only q, reach\_band or a filter lists every approved creator those match, with no audience limit. A call that names none of those while your brand has no audience on file is refused with 400 filter\_required: name an audience. It pages through the approved creators that match, best fit for your audience first: limit (default 24, at most 50) and offset, with total saying how many there are and priced how many of them have something on sale now. catalog is the whole network, whatever you filtered: catalog.approved is every approved creator and catalog.priced how many of them are bookable now, the same numbers the app and the site show; it is left out when the network cannot be counted right now, never guessed. A creator with nothing on sale carries price\_estimate (an estimated range, never a price) and ask\_price true: creator\_ask\_price (POST /creators/{id}/price-request) asks our team for its price, the same ask as the app's button; the price then shows on the creator and is held for you for 48 hours, asking again answers already true, and the creator is never contacted directly. Rows carry no handle; creator\_get opens one creator in full and counts as one reveal. No creator read carries an X handle or an x.com link: a creator's handle and profile link show once your order for a plan with that creator is paid, on that plan's quote (plan\_quote). Creator views are one pool per workspace: 300 different creators shown or opened a day (since midnight UTC), shared by the app and every API key of your brand; a creator already seen today, in the app or through any key, is free. Past 300, a list, and an opening of a creator not yet seen today, answers 429 rate\_limited with reason daily\_seen, scope workspace and limit 300; a page served near the end of the pool lists only the creators that fit, so total can be larger than the creators returned. Each key also has its own limits, and all of your brand's keys together share one ceiling of the same size: 20 creator reads a minute, 60 searches a day and 60 creators opened a day (one reopened the same day is free). Past one of those, a read answers 429 rate\_limited with Retry-After, the reason, and scope (key for this key, api for the brand's ceiling). - Every write takes an idempotency\_key (8 to 128 characters: letters, digits, dot, underscore, colon or hyphen). A retry with the same key and arguments returns the first answer and never runs twice. ## What bookable means A creator is bookable (on sale) when all of these hold: our team approved the creator after vetting (verified and active); our vetting 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. priced in creators\_search, catalog.priced and the network facts count creators by it; inventory and resolve\_audience give bookable\_nodes by the same rule (never above the network's), and priced\_units counts those creators' posts on sale at a current price, not creators. ## The mandate A brand sets a mandate on each key in Developers: the most a plan may total, a monthly cap, the channels, whether the key may sign, an expiry, and the brand terms a person accepted for it. A write outside it is refused before any spend with mandate\_refused, the limit and how much over, and escalate: true. Take that to a person at the brand; do not retry. A plan over its campaign's budget is refused with conflict, reason over\_budget and over\_by\_cents, always, and so is a creator that would take it over: plan\_add\_creator and plan\_swap\_creator answer conflict, reason over\_budget, with budget\_cents and remaining\_cents (the room before that creator), and leave the plan as it was. plan\_quote says when a plan is over its budget in over\_budget (budget\_cents, total\_cents, over\_by\_cents), at current prices when a creator's price rose past it, and its policy refuses with over\_budget. Nobody approves an overage, the brand included, and no field confirms one: remove a creator until the plan fits, or ask a person at the brand to raise the budget, then quote again. ## Errors Every error carries a code and a message: bad\_request, filter\_required, unauthorized, forbidden, not\_found, method\_not\_allowed, conflict, idempotency\_conflict, in\_progress, unprocessable, mandate\_refused, rate\_limited, unavailable, internal. A plan that changed since its quote is refused with conflict and reason terms\_changed: quote again. ## Feedback When a call fails unexpectedly, a field is empty or wrong, or a capability is missing, call feedback\_send with identifiers only. Check feedback\_list first so one issue is reported once. ## Tools - inventory (inventory:read): Network coverage. REST: GET /api/v1/inventory. - resolve\_audience (audience:read): Resolve an audience. REST: GET /api/v1/audience. - campaign\_status (campaigns:read): Campaign status. REST: GET /api/v1/campaigns and /api/v1/campaigns/{id}. - evidence (evidence:read): Proof of delivery. REST: GET /api/v1/evidence. - results (results:read): Results. REST: GET /api/v1/results. - brain\_get (brain:read): Company context. REST: GET /api/v1/brain. - creators\_search (creators:read): Find creators. REST: GET /api/v1/creators. - creator\_get (creators:read): One creator. REST: GET /api/v1/creators/{id}. - creator\_ask\_price (creators:read): Ask for a price. REST: POST /api/v1/creators/{id}/price-request. - plan\_quote (campaigns:read): Quote a plan. REST: GET /api/v1/plans/{id}/quote. - create\_campaign (campaigns:write, write): Start a campaign. REST: POST /api/v1/campaigns. - plan\_add\_creator (campaigns:write, write): Add a creator. REST: POST /api/v1/plans/{id}/lines. - plan\_remove\_creator (campaigns:write, write): Remove a creator. REST: DELETE /api/v1/plans/{id}/lines/{line\_id}. - plan\_move\_dates (campaigns:write, write): Move a plan's dates. REST: POST /api/v1/plans/{id}/dates. - plan\_swap\_creator (campaigns:write, write): Swap a creator. REST: POST /api/v1/plans/{id}/lines/{line\_id}/swap. - set\_creator\_guidelines (campaigns:write, write): Set the creator guidelines. REST: POST /api/v1/campaigns/{id}/creator-guidelines. - approve\_plan (plans:approve, write): Approve and get the pay link. REST: POST /api/v1/plans/{id}/approve. - archive\_campaign (campaigns:write, write): Archive a campaign. REST: POST /api/v1/campaigns/{id}/archive. - rename\_campaign (campaigns:write, write): Rename a campaign. REST: PATCH /api/v1/campaigns/{id}. - delete\_campaign (campaigns:write, write): Delete a draft campaign. REST: DELETE /api/v1/campaigns/{id}. - feedback\_send (any key): Send feedback. REST: POST /api/v1/feedback. - feedback\_list (any key): Your feedback. REST: GET /api/v1/feedback. On this page - [Connect your agent](#connect) - [Three recipes](#recipes) - [The flow](#the-flow) - [Limits](#limits) - [What bookable means](#what-bookable-means) - [The mandate](#the-mandate) - [Errors](#errors) - [Feedback](#feedback) - [Tools](#tools) [![distribution.tech](https://distribution.tech/brand/wordmark-light.svg)![distribution.tech](https://distribution.tech/brand/wordmark.svg)](https://distribution.tech/) Your agent buys your distribution. Distribution we run for - ClickUp - Gushwork - Tab Platform - [How it works](https://distribution.tech/how-it-works) - [Network](https://distribution.tech/network) - [Workspace](https://app.distribution.tech/login) - [For your agents](https://distribution.tech/distribution) Solutions - [Product launch](https://distribution.tech/solutions/product-launch) - [Funding announcement](https://distribution.tech/solutions/funding-announcement) - [Feature release](https://distribution.tech/solutions/feature-release) - [For brands](https://distribution.tech/for-brands) - [For creators](https://distribution.tech/for-creators) Resources - [Blog](https://distribution.tech/blog) - [Launch playbook](https://distribution.tech/playbook) - [X creator rates](https://distribution.tech/rates/x-creators) Company - [Customers](https://distribution.tech/customers) - [Pricing](https://distribution.tech/pricing) - [Changelog](https://distribution.tech/changelog) - [Build a distribution plan](https://app.distribution.tech/login) - [Join the creator network](https://distribution.tech/for-creators#apply) - [Log in](https://app.distribution.tech/login) Legal - [Privacy](https://distribution.tech/privacy) - [Terms](https://distribution.tech/terms) © 2026 distribution.tech [Contact: team@distribution.tech](mailto:team@distribution.tech)Cookie settings Light Dark System