Overview
Named creators, all-in prices, totals, payment options, the fingerprint and the mandate's answer
Scope: campaigns:read.
- Endpoint
GET https://app.distribution.tech/api/v1/plans/{id}/quote- Scope
campaigns:read- Changes data
- No, a read
- MCP tool
- plan_quote
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | Yes |
Request with curl
Set DISTRIBUTION_API_KEY to a key from Developers with the campaigns:read scope, and each path variable to an id from an earlier answer. The body carries the required fields.
curl "https://app.distribution.tech/api/v1/plans/$PLAN_ID/quote" \
-H "Authorization: Bearer $DISTRIBUTION_API_KEY"Response
200 OK. The body has these fields:
| Name | Type | Required | Description |
|---|---|---|---|
plan_id | string (uuid) | No | |
campaign_id | string (uuid) | No | |
version | integer | No | |
status | one of "awaiting_approval", "approved" | No | |
currency | string | No | |
launch_window_start | string (date) | No | |
launch_window_end | string (date) | No | |
terms_fingerprint | string | No | Send exactly this to approve. It changes when a line, a price or the dates change. |
total_cents | integer | No | |
totals | object | No | creators, total_cents, views_low, views_high, unmeasured, cpm_low_cents, cpm_high_cents, tiers, budget_cents, remaining_cents. |
lines | array of object | No | |
payment_options | array of object | No | |
agent_payment | one of "checkout", "team_invoice" | No | |
brand_terms | object | No | |
mandate | object or null | No | |
policy | object | No | allowed: whether this key's mandate lets it sign now; refusal: the reason and numbers when not (over_budget when the plan is over the campaign's budget, which no mandate can approve: remove a creator or have the brand raise the budget). |
blocked_lines | array of string (uuid) | No | |
over_budget | object or null | No | The plan over its campaign's budget: budget_cents, total_cents and over_by_cents, at current prices when a creator's price rose past the budget (the plan then keeps its earlier prices, so total_cents alone reads as within it). Null within the budget, with no budget, or once signed. Approval refuses it until a creator is removed or the budget is raised. |
order | object or null | No | |
valid_while | "terms_fingerprint_unchanged" | No |
{
"plan_id": "<uuid>",
"campaign_id": "<uuid>",
"version": 0,
"status": "awaiting_approval",
"currency": "<string>",
"launch_window_start": "<date>",
"launch_window_end": "<date>",
"terms_fingerprint": "<string>",
"total_cents": 0,
"totals": {},
"lines": [
{
"id": "<uuid>",
"creator": {
"id": "<uuid>",
"name": "<string>",
"handle": "<string>",
"profile_url": "<string>",
"avatar_url": "<uri>",
"followers": 0
},
"creator_id": "<uuid>",
"unit_id": "<uuid>",
"stage_id": "planned",
"stage": "<string>",
"channel": "<string>",
"channel_label": "<string>",
"format": "<string>",
"deliverable": "<string>",
"scheduled_date": "<date>",
"price_cents": 0,
"vetting": "<string>",
"reason": "<string>",
"expected_views_low": 0,
"expected_views_high": 0,
"on_sale": false
}
],
"payment_options": [
{
"rail": "checkout",
"label": "<string>",
"clears": "<string>"
}
],
"agent_payment": "checkout",
"brand_terms": {
"current_version": "<string>",
"current_number": 0,
"url": "<string>",
"accepted_for_this_key": "<string>",
"accepted_number_for_this_key": 0
},
"mandate": {
"key_id": "<uuid>",
"version": 0,
"max_plan_cents": 0,
"monthly_cap_cents": 0,
"channels": [
"<string>"
],
"may_approve": false,
"may_exceed_budget": false,
"expires_at": "<date-time>",
"updated_at": "<date-time>",
"spent_this_month_cents": 0,
"terms_version": "<string>",
"terms_accepted_at": "<date-time>",
"terms_accepted_email": "<string>"
},
"policy": {
"allowed": false,
"refusal": {}
},
"blocked_lines": [
"<uuid>"
],
"over_budget": {
"budget_cents": 0,
"total_cents": 0,
"over_by_cents": 0
},
"order": {},
"valid_while": "terms_fingerprint_unchanged"
}Errors
| Status | When |
|---|---|
400 | A parameter is not valid: details.problems names each field and what it accepts. |
401 | No API key, an unknown one, or a revoked one. |
403 | The key does not have this endpoint's scope. |
404 | No plan of yours has that id. |
429 | 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). |
500 | internal: the request failed on our side. Try again. |
503 | unavailable: the service or this part of it is not reachable right now. Try again shortly. |
Related endpoints
POST /plans/{id}/approve: Approve and get the pay linkPOST /plans/{id}/dates: Move a plan's datesPOST /plans/{id}/lines: Add a creatorDELETE /plans/{id}/lines/{line_id}: Remove a creatorPOST /plans/{id}/lines/{line_id}/swap: Swap a creator
Get access
Keys are created in Developers once your brand is approved. Connect an agent to ask for access, then read the agent guide for the full flow.