{"openapi":"3.1.0","info":{"title":"FORTVISION Platform API","version":"3.0.1","description":"Read access to one FORTVISION workspace: leads, contacts, eCommerce customers, CRM tasks,\nad campaigns, conversations, automations and reports.\n\n**Authentication** — a bearer token created in the app under Integrations → Programmatic access.\nSend it as `Authorization: Bearer fvmcp_…`. Tokens carry scopes, expire, and can be revoked or\nrotated at any time. The token acts as the user who created it: it can never see more than they can.\n\n**Tenancy** — a token is bound to one workspace. Ids from another workspace return 404, never data.\nThe workspace is resolved from the token; it can never be supplied by the client.\n\n**Pagination** — every list takes `page` and `pageSize` (max 100) and returns a `pagination` object.\nThere is no way to request an unbounded result set.\n\n**Rate limits** — per token and per workspace, per minute. Exceeding either returns 429.\n\n**Errors** — `{ \"ok\": false, \"error\": { \"code\": \"...\", \"message\": \"...\" } }` with an HTTP status to match.\nCodes: invalid_input, unauthorized, forbidden, not_found, rate_limited, unavailable, timeout, internal.\n\n**Idempotency** — every operation here is a read and therefore idempotent. Write operations, when they\nship, will require an `Idempotency-Key` header and an explicit confirmation step.\n\nThe same capabilities are available to LLM clients over the Model Context Protocol at `/mcp`."},"servers":[{"url":"https://app.fortvision.com/api/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"fvmcp token","description":"Workspace access token created in FORTVISION → Integrations."}},"responses":{"Error":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_input","unauthorized","forbidden","not_found","conflict","rate_limited","unavailable","timeout","internal"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":true}}},"requestId":{"type":"string"}}},"example":{"ok":false,"error":{"code":"not_found","message":"No lead with that id is visible to this token."},"requestId":"req_2f1c9a4b7d0e5a86"}}}}}},"x-scopes":[{"name":"leads.read","risk":"read","stage":1,"description":"Read leads, their statuses, owners and sources.","grantable":true},{"name":"contacts.read","risk":"read","stage":1,"description":"Read contacts, their lists (My Lists), records, Due Date, notes, tasks and activity timeline.","grantable":true},{"name":"customers.read","risk":"read","stage":1,"description":"Read eCommerce customers, orders and store list.","grantable":true},{"name":"tasks.read","risk":"read","stage":1,"description":"Read CRM tasks.","grantable":true},{"name":"deals.read","risk":"read","stage":1,"description":"Read sales-pipeline deals, stage history and the pipeline forecast.","grantable":true},{"name":"campaigns.read","risk":"read","stage":1,"description":"Read ad campaigns and their performance metrics.","grantable":true},{"name":"conversations.read","risk":"read","stage":1,"description":"Read WhatsApp / SMS / social conversations.","grantable":true},{"name":"agents.read","risk":"read","stage":1,"description":"Read automations (journeys) and their run stats.","grantable":true},{"name":"reports.read","risk":"read","stage":1,"description":"Read aggregate reports (lead sources, conversions, customer summary).","grantable":true},{"name":"linkedin.read","risk":"read","stage":1,"description":"Read LinkedIn outreach: senders, prospect lists, sequences and their stats, inbox conversations.","grantable":true},{"name":"wallet.read","risk":"read","stage":1,"description":"Read the Wallet loyalty module: cards, member counts and funnel, member search, recent club activity.","grantable":true},{"name":"projects.read","risk":"read","stage":1,"description":"Read Projects boards: groups, columns, items and their status, owners and column values.","grantable":true},{"name":"pages.read","risk":"read","stage":1,"description":"Read landing pages and their performance (views, leads, conversion rate).","grantable":true},{"name":"social.read","risk":"read","stage":1,"description":"Read the social content calendar: posts, statuses, schedule and performance.","grantable":true},{"name":"coupons.read","risk":"read","stage":1,"description":"Read coupons and their issue/redemption/revenue stats.","grantable":true},{"name":"meetings.read","risk":"read","stage":1,"description":"Read booking pages and booked meetings.","grantable":true},{"name":"leads.write","risk":"write","stage":2,"description":"Create and update leads, statuses and owners.","grantable":true},{"name":"contacts.write","risk":"write","stage":2,"description":"Update existing contact records by id: Due Date, status, owner, rating, notes (singly or in batches). Never creates or deletes contacts.","grantable":true},{"name":"customers.write","risk":"write","stage":2,"description":"Update customer records.","grantable":true},{"name":"tasks.write","risk":"write","stage":2,"description":"Create, update and complete tasks.","grantable":true},{"name":"deals.write","risk":"write","stage":2,"description":"Create deals, move them between pipeline stages (incl. Closed Won / Lost) and link contacts and companies.","grantable":true},{"name":"notes.write","risk":"write","stage":2,"description":"Add notes to leads, contacts, companies and deals.","grantable":true},{"name":"messages.draft","risk":"write","stage":2,"description":"Create email / SMS / WhatsApp drafts (never sends).","grantable":true},{"name":"linkedin.write","risk":"write","stage":2,"description":"Create and edit LinkedIn sequences (as drafts), import prospects into lists, pause sequences. Never launches or sends.","grantable":true},{"name":"projects.write","risk":"write","stage":2,"description":"Create Projects boards and items; update item status, owners, dates, column values and comments.","grantable":true},{"name":"agents.write","risk":"write","stage":2,"description":"Enable or pause automations (journeys). Reversible; never edits the flow.","grantable":true},{"name":"pages.write","risk":"write","stage":2,"description":"Create landing pages (AI-generated), edit their content and settings, manage landing-page lists.","grantable":true},{"name":"social.write","risk":"write","stage":2,"description":"Create and edit social posts as drafts, generate post ideas. Never schedules or publishes.","grantable":true},{"name":"coupons.write","risk":"write","stage":2,"description":"Create coupons, pause/resume them, issue a code to a contact.","grantable":true},{"name":"meetings.write","risk":"write","stage":2,"description":"Create and edit booking pages.","grantable":true},{"name":"messages.send","risk":"high","stage":3,"description":"Send email / SMS / WhatsApp. Requires explicit confirmation per send.","grantable":true},{"name":"linkedin.send","risk":"high","stage":3,"description":"Launch or resume LinkedIn sequences and send LinkedIn messages. Requires explicit confirmation per action.","grantable":true},{"name":"campaigns.write","risk":"high","stage":3,"description":"Activate, pause or modify ad campaigns.","grantable":true},{"name":"budgets.write","risk":"high","stage":3,"description":"Change campaign budgets and bids.","grantable":true},{"name":"social.publish","risk":"high","stage":3,"description":"Schedule or publish social posts to connected pages. Requires explicit confirmation per action.","grantable":true},{"name":"records.delete","risk":"high","stage":3,"description":"Delete records. Irreversible.","grantable":true},{"name":"orders.write","risk":"high","stage":3,"description":"Cancel orders, change shipping addresses and refund payments in connected stores (WooCommerce, Shopify, Wix, the WordPress plugin). Refunds need explicit confirmation per action.","grantable":true},{"name":"admin.integrations","risk":"high","stage":3,"description":"Manage integrations and access tokens.","grantable":true}],"paths":{"/workspace":{"get":{"operationId":"get_workspace_info","summary":"Identify the workspace this token acts in, the scopes it holds, the lead statuses this account uses, and which data sources (Facebook, Google Ads, DV360, email, WhatsApp, stores) are actually connected","description":"Identify the workspace this token acts in, the scopes it holds, the lead statuses this account uses, and which data sources (Facebook, Google Ads, DV360, email, WhatsApp, stores) are actually connected. Call this FIRST in a session: it tells you which of the other tools can return anything, so you do not guess.\n\nRequired scope: `leads.read`. Risk level: `read`.","tags":["leads"],"security":[{"bearerAuth":["leads.read"]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"workspace":{"type":"object","properties":{"id":{"type":"string","description":"Workspace / account id."},"isRestrictedUser":{"type":"boolean","description":"True when the token owner is a restricted (grant-scoped) user."},"role":{"type":"string","description":"Role of the token owner (\"\" when none)."}},"additionalProperties":true,"required":["id","isRestrictedUser","role"],"description":"The workspace this token is scoped to."},"user":{"type":"object","properties":{"email":{"type":"string","description":"User email."},"name":{"type":"string","description":"User display name (\"\" when unset)."}},"additionalProperties":true,"required":["email","name"],"description":"The user the token acts as."},"token":{"type":"object","properties":{"id":{"type":"string","description":"Token id."},"name":{"type":"string","description":"Token label."},"scopes":{"type":"array","items":{"type":"string"},"description":"Granted scopes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry (\"\" when it does not expire)."}},"additionalProperties":true,"required":["id","name","scopes","expiresAt"],"description":"The API token in use."},"leadStatuses":{"type":"array","items":{"type":"string"},"description":"The lead pipeline statuses this workspace uses, in order."},"connections":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Integration key, e.g. meta-ads, google-ads, gmail."},"name":{"type":"string","description":"Integration display name."},"category":{"type":"string","description":"Group, e.g. Ads, Social, Email."},"status":{"type":"string","description":"connected | expiring | expired | missing."}},"additionalProperties":true},"description":"Connected integrations and their health; absent when the integrations endpoint is unavailable."}},"additionalProperties":true,"required":["ok","requestId","workspace","user","token","leadStatuses"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/leads":{"get":{"operationId":"search_leads","summary":"Search leads across every source in this workspace (Facebook lead forms, manual/CSV imports, landing pages)","description":"Search leads across every source in this workspace (Facebook lead forms, manual/CSV imports, landing pages). Matches `query` against name, email, phone and campaign name. Use it to answer \"who came in\", \"find the lead called X\", \"leads from campaign Y last week\". Returns a page of summary records — call get_lead for the full form answers.\n\nRequired scope: `leads.read`. Risk level: `read`.","tags":["leads"],"security":[{"bearerAuth":["leads.read"]}],"parameters":[{"name":"query","in":"query","required":false,"description":"Free text: name, email, phone (4+ digits), lead id, or campaign name.","schema":{"type":"string","maxLength":120}},{"name":"status","in":"query","required":false,"description":"Exact pipeline status.","schema":{"type":"string","enum":["New","Contacted","Qualified","Scheduled a Meeting","Proposal","Negotiation","Won","Lost","Unresponsive"]}},{"name":"source","in":"query","required":false,"description":"Which system the lead came from.","schema":{"type":"string","enum":["facebook","manual","landing_page"]}},{"name":"owner","in":"query","required":false,"description":"Assigned owner (email or name), exact match.","schema":{"type":"string","maxLength":120}},{"name":"band","in":"query","required":false,"description":"Lead-score band: hot, warm, cold, won or lost (hot = at or above the workspace hot threshold).","schema":{"type":"string","enum":["hot","warm","cold","won","lost"]}},{"name":"campaignId","in":"query","required":false,"description":"Restrict to one ad campaign id.","schema":{"type":"string","maxLength":60}},{"name":"sort","in":"query","required":false,"description":"Result order. Default newest first.","schema":{"type":"string","enum":["created_desc","created_asc","name_asc","rating_desc","score_desc"],"default":"created_desc"}},{"name":"dateFrom","in":"query","required":false,"description":"Only records at or after this ISO 8601 date/datetime (e.g. 2026-07-01).","schema":{"type":"string","maxLength":40}},{"name":"dateTo","in":"query","required":false,"description":"Only records at or before this ISO 8601 date/datetime.","schema":{"type":"string","maxLength":40}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"leads":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Lead id; source-specific (Facebook lead id, manual _id or landing-page submission id)."},"source":{"type":"string","enum":["facebook","manual","landing_page"],"description":"Which store the lead came from."},"name":{"type":"string","description":"Full name (\"\" when unknown)."},"email":{"type":"string","description":"Email, lower-cased (\"\" when unknown)."},"phone":{"type":"string","description":"Phone as entered (\"\" when unknown)."},"status":{"type":"string","description":"Pipeline status; normally one of get_workspace_info.leadStatuses (default \"New\")."},"rating":{"type":"number","description":"Human-set rating (0 when unrated)."},"owner":{"type":"string","description":"Assigned owner (email or name, \"\" when unassigned)."},"dueDate":{"type":"string","description":"The board's Due Date (yyyy-mm-dd), \"\" when none is set."},"score":{"type":"number","description":"Lead score 0-100 from the hourly scoring sweep; absent when not scored yet."},"scoreBand":{"type":"string","enum":["hot","warm","cold","won","lost"],"description":"Score band; absent when not scored yet."},"createdAt":{"type":"string","description":"ISO 8601 creation time (\"\" when unknown)."},"updatedAt":{"type":"string","description":"ISO 8601 time of the last human edit/note, else createdAt."},"campaignName":{"type":"string","description":"Ad campaign / UTM campaign name (\"\" when none)."},"formName":{"type":"string","description":"Lead form name (\"Landing page\" for LP leads, \"\" when none)."},"pageName":{"type":"string","description":"Facebook page or landing-page name (\"\" when none)."},"platform":{"type":"string","description":"Origin platform, e.g. facebook, instagram, manual, landing_page."},"isOrganic":{"type":"boolean","description":"True when the lead did not come from a paid click."},"hasNote":{"type":"boolean","description":"True when the lead carries at least one note (edit layer or CRM)."}},"additionalProperties":true,"required":["id","source","name","email","phone","status","rating","owner","dueDate","createdAt","updatedAt","campaignName","formName","pageName","platform","isOrganic","hasNote"]},"description":"Matching leads for this page."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (max 100)."},"total":{"type":"integer","description":"Total matching rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the (already filtered and sorted) result set."},"sources":{"type":"object","properties":{"facebook":{"type":"object","properties":{"count":{"type":"integer","description":"Rows read from this store (0 when unavailable)."},"stale":{"type":"boolean","description":"True when the cached form leads are stale; only present when the store loaded."},"unavailable":{"type":"string","description":"Set only when the store failed to load: short reason (≤140 chars)."}},"additionalProperties":true,"required":["count"],"description":"Facebook lead-form store: rows contributed, or why it was unavailable."},"manual":{"type":"object","properties":{"count":{"type":"integer","description":"Rows read from this store (0 when unavailable)."},"unavailable":{"type":"string","description":"Set only when the store failed to load: short reason (≤140 chars)."}},"additionalProperties":true,"required":["count"],"description":"Manual / CSV-import store: rows contributed, or why it was unavailable."},"landing_page":{"type":"object","properties":{"count":{"type":"integer","description":"Rows read from this store (0 when unavailable)."},"unavailable":{"type":"string","description":"Set only when the store failed to load: short reason (≤140 chars)."}},"additionalProperties":true,"required":["count"],"description":"Landing-page submission store: rows contributed, or why it was unavailable."}},"additionalProperties":true,"required":["facebook","manual","landing_page"],"description":"Which lead stores contributed to the working set; a failed store reports `unavailable` rather than under-counting."},"workingSetTruncated":{"type":"boolean","description":"True when the merged lead set exceeded the working-set cap (200k) and was cut."},"workingSet":{"type":"object","properties":{"hit":{"type":"boolean","description":"true = served from the workspace cache (invalidated by every lead write, max 2 min old)."},"ageMs":{"type":"integer","description":"Age of the cached set in ms (0 on a fresh load)."},"leads":{"type":"integer","description":"Rows in the merged set."}},"additionalProperties":true,"description":"How the merged lead set was obtained."}},"additionalProperties":true,"required":["ok","requestId","leads","pagination","sources","workingSetTruncated"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"create_lead","summary":"Add a contact to the Leads board","description":"Add a contact to the Leads board. Needs at least an email or a phone number. If someone with that email or phone already exists, nothing is created and the existing lead is returned — so calling this twice is safe. Ad-platform leads arrive on their own; this is for contacts you are adding by hand.\n\nRequired scope: `leads.write`. Risk level: `write`.","tags":["leads"],"security":[{"bearerAuth":["leads.write"]}],"parameters":[{"name":"name","in":"query","required":false,"description":"Full name.","schema":{"type":"string","maxLength":160}},{"name":"email","in":"query","required":false,"description":"Email address.","schema":{"type":"string","maxLength":160}},{"name":"phone","in":"query","required":false,"description":"Phone number, ideally in +country format.","schema":{"type":"string","maxLength":60}},{"name":"status","in":"query","required":false,"description":"Starting pipeline status. Defaults to New.","schema":{"type":"string","enum":["New","Contacted","Qualified","Scheduled a Meeting","Proposal","Negotiation","Won","Lost","Unresponsive"]}},{"name":"owner","in":"query","required":false,"description":"Assign to this user (their email).","schema":{"type":"string","maxLength":120}},{"name":"campaign","in":"query","required":false,"description":"Campaign or source name to record against the lead.","schema":{"type":"string","maxLength":160}},{"name":"sourceLabel","in":"query","required":false,"description":"Where this contact came from, shown in the Form/Page column. Defaults to \"API\".","schema":{"type":"string","maxLength":120}},{"name":"utmSource","in":"query","required":false,"description":"utm_source to record.","schema":{"type":"string","maxLength":80}},{"name":"utmMedium","in":"query","required":false,"description":"utm_medium to record.","schema":{"type":"string","maxLength":80}},{"name":"utmCampaign","in":"query","required":false,"description":"utm_campaign to record.","schema":{"type":"string","maxLength":120}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["lead"],"description":"Always \"lead\"."},"targetId":{"type":"string","description":"Id of the created lead, or of the existing duplicate when created=false."},"created":{"type":"boolean","description":"False when a contact with the same email/phone already existed (nothing written)."},"duplicateOf":{"type":"string","description":"Only when created=false: id of the existing contact."},"lead":{"type":"object","properties":{"id":{"type":"string","description":"Lead id (manual_…)."},"source":{"type":"string","enum":["manual"],"description":"Only when created=true: always \"manual\"."},"name":{"type":"string","description":"Contact name, \"\" when none."},"email":{"type":"string","description":"Lowercased email, \"\" when none."},"phone":{"type":"string","description":"Phone as supplied, \"\" when none."},"status":{"type":"string","description":"Only when created=true: initial pipeline status (default \"New\")."},"owner":{"type":"string","description":"Only when created=true: assigned owner, \"\" when unassigned."}},"additionalProperties":true,"required":["id","name","email","phone"],"description":"The created contact (or the existing duplicate)."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","created","lead"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/leads/{id}":{"get":{"operationId":"get_lead","summary":"Full detail for one lead: every form answer, custom board fields, the note a human left, the campaign/ad set/ad it came from, and any CRM tasks attached to it","description":"Full detail for one lead: every form answer, custom board fields, the note a human left, the campaign/ad set/ad it came from, and any CRM tasks attached to it. Use the id returned by search_leads.\n\nRequired scope: `leads.read`. Risk level: `read`.","tags":["leads"],"security":[{"bearerAuth":["leads.read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Lead id from search_leads.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"lead":{"type":"object","properties":{"id":{"type":"string","description":"Lead id; source-specific (Facebook lead id, manual _id or landing-page submission id)."},"source":{"type":"string","enum":["facebook","manual","landing_page"],"description":"Which store the lead came from."},"name":{"type":"string","description":"Full name (\"\" when unknown)."},"email":{"type":"string","description":"Email, lower-cased (\"\" when unknown)."},"phone":{"type":"string","description":"Phone as entered (\"\" when unknown)."},"status":{"type":"string","description":"Pipeline status; normally one of get_workspace_info.leadStatuses (default \"New\")."},"rating":{"type":"number","description":"Human-set rating (0 when unrated)."},"owner":{"type":"string","description":"Assigned owner (email or name, \"\" when unassigned)."},"dueDate":{"type":"string","description":"The board's Due Date (yyyy-mm-dd), \"\" when none is set."},"score":{"type":"number","description":"Lead score 0-100 from the hourly scoring sweep; absent when not scored yet."},"scoreBand":{"type":"string","enum":["hot","warm","cold","won","lost"],"description":"Score band; absent when not scored yet."},"createdAt":{"type":"string","description":"ISO 8601 creation time (\"\" when unknown)."},"updatedAt":{"type":"string","description":"ISO 8601 time of the last human edit/note, else createdAt."},"campaignName":{"type":"string","description":"Ad campaign / UTM campaign name (\"\" when none)."},"formName":{"type":"string","description":"Lead form name (\"Landing page\" for LP leads, \"\" when none)."},"pageName":{"type":"string","description":"Facebook page or landing-page name (\"\" when none)."},"platform":{"type":"string","description":"Origin platform, e.g. facebook, instagram, manual, landing_page."},"isOrganic":{"type":"boolean","description":"True when the lead did not come from a paid click."},"hasNote":{"type":"boolean","description":"True when the lead carries at least one note (edit layer or CRM)."},"campaign":{"type":"object","properties":{"id":{"type":"string","description":"Platform id (\"\" when unknown)."},"name":{"type":"string","description":"Display name (\"\" when unknown)."}},"additionalProperties":true,"required":["id","name"],"description":"Ad campaign the lead came from."},"adSet":{"type":"object","properties":{"id":{"type":"string","description":"Platform id (\"\" when unknown)."},"name":{"type":"string","description":"Display name (\"\" when unknown)."}},"additionalProperties":true,"required":["id","name"],"description":"Ad set (Meta) the lead came from."},"ad":{"type":"object","properties":{"id":{"type":"string","description":"Platform id (\"\" when unknown)."},"name":{"type":"string","description":"Display name (\"\" when unknown)."}},"additionalProperties":true,"required":["id","name"],"description":"Ad the lead came from."},"form":{"type":"object","properties":{"id":{"type":"string","description":"Platform id (\"\" when unknown)."},"name":{"type":"string","description":"Display name (\"\" when unknown)."}},"additionalProperties":true,"required":["id","name"],"description":"Lead form / landing page the lead was submitted through."},"page":{"type":"object","properties":{"id":{"type":"string","description":"Platform id (\"\" when unknown)."},"name":{"type":"string","description":"Display name (\"\" when unknown)."}},"additionalProperties":true,"required":["id","name"],"description":"Facebook page or landing page."},"formAnswers":{"type":"object","additionalProperties":true,"description":"Raw form answers keyed by lower-cased field name (values ≤500 chars)."},"customFields":{"type":"object","additionalProperties":true,"description":"Workspace custom board columns keyed by column id (string/number values)."},"note":{"type":"string","description":"Legacy edit-layer note text (≤2000 chars, \"\" when none)."},"tasks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Task id."},"title":{"type":"string","description":"Task title (≤200 chars)."},"done":{"type":"boolean","description":"True when completed."},"priority":{"type":"string","description":"API priority: low | normal | high | urgent, or \"\" when none."},"priorityLabel":{"type":"string","description":"Priority label as stored on the board (e.g. Medium)."},"owner":{"type":"string","description":"Assignee (\"\" when unassigned)."},"dueAt":{"type":"string","description":"ISO 8601 due datetime (end of day when no time), \"\" when no due date."},"relatedTo":{"type":["object","null"],"properties":{"type":{"type":"string","description":"Entity type, e.g. contact, deal, company."},"id":{"type":"string","description":"Entity id."}},"additionalProperties":true,"required":["type","id"],"description":"Linked CRM entity, or null."},"createdAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."},"updatedAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."}},"additionalProperties":true,"required":["id","title","done","priority","priorityLabel","owner","dueAt","relatedTo","createdAt","updatedAt"]},"description":"Up to 20 CRM tasks attached to this lead (empty when the CRM is unreadable)."},"notes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Note id."},"text":{"type":"string","description":"Note body (≤2000 chars)."},"kind":{"type":"string","description":"Note kind, e.g. note, call, meeting (\"\" when unset)."},"author":{"type":"string","description":"Author email (\"\" when unknown)."},"createdAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."}},"additionalProperties":true,"required":["id","text","kind","author","createdAt"]},"description":"Up to 20 CRM notes, as written by add_lead_note (empty when unreadable)."}},"additionalProperties":true,"required":["id","source","name","email","phone","status","rating","owner","dueDate","createdAt","updatedAt","campaignName","formName","pageName","platform","isOrganic","hasNote","campaign","adSet","ad","form","page","formAnswers","customFields","note","tasks","notes"],"description":"Full lead detail."}},"additionalProperties":true,"required":["ok","requestId","lead"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/leads/stale":{"get":{"operationId":"list_stale_leads","summary":"Open leads nobody has touched in `days` (default 14), oldest first, with how long each has been idle","description":"Open leads nobody has touched in `days` (default 14), oldest first, with how long each has been idle. \"Touched\" means created, edited or noted in the app. Won/Lost/Unresponsive leads are excluded. Use it for pipeline hygiene questions (\"what is going cold?\").\n\nRequired scope: `leads.read`. Risk level: `read`.","tags":["leads"],"security":[{"bearerAuth":["leads.read"]}],"parameters":[{"name":"days","in":"query","required":false,"description":"Idle threshold in days.","schema":{"type":"integer","minimum":1,"maximum":365,"default":14}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"staleAfterDays":{"type":"integer","description":"The idle threshold applied (1-365, default 14)."},"leads":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Lead id; source-specific (Facebook lead id, manual _id or landing-page submission id)."},"source":{"type":"string","enum":["facebook","manual","landing_page"],"description":"Which store the lead came from."},"name":{"type":"string","description":"Full name (\"\" when unknown)."},"email":{"type":"string","description":"Email, lower-cased (\"\" when unknown)."},"phone":{"type":"string","description":"Phone as entered (\"\" when unknown)."},"status":{"type":"string","description":"Pipeline status; normally one of get_workspace_info.leadStatuses (default \"New\")."},"rating":{"type":"number","description":"Human-set rating (0 when unrated)."},"owner":{"type":"string","description":"Assigned owner (email or name, \"\" when unassigned)."},"dueDate":{"type":"string","description":"The board's Due Date (yyyy-mm-dd), \"\" when none is set."},"score":{"type":"number","description":"Lead score 0-100 from the hourly scoring sweep; absent when not scored yet."},"scoreBand":{"type":"string","enum":["hot","warm","cold","won","lost"],"description":"Score band; absent when not scored yet."},"createdAt":{"type":"string","description":"ISO 8601 creation time (\"\" when unknown)."},"updatedAt":{"type":"string","description":"ISO 8601 time of the last human edit/note, else createdAt."},"campaignName":{"type":"string","description":"Ad campaign / UTM campaign name (\"\" when none)."},"formName":{"type":"string","description":"Lead form name (\"Landing page\" for LP leads, \"\" when none)."},"pageName":{"type":"string","description":"Facebook page or landing-page name (\"\" when none)."},"platform":{"type":"string","description":"Origin platform, e.g. facebook, instagram, manual, landing_page."},"isOrganic":{"type":"boolean","description":"True when the lead did not come from a paid click."},"hasNote":{"type":"boolean","description":"True when the lead carries at least one note (edit layer or CRM)."},"idleDays":{"type":"integer","description":"Whole days since the last touch (created / edited / noted)."}},"additionalProperties":true,"required":["id","source","name","email","phone","status","rating","owner","dueDate","createdAt","updatedAt","campaignName","formName","pageName","platform","isOrganic","hasNote","idleDays"]},"description":"Open leads untouched for at least staleAfterDays, oldest touch first."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (max 100)."},"total":{"type":"integer","description":"Total matching rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the (already filtered and sorted) result set."},"sources":{"type":"object","properties":{"facebook":{"type":"object","properties":{"count":{"type":"integer","description":"Rows read from this store (0 when unavailable)."},"stale":{"type":"boolean","description":"True when the cached form leads are stale; only present when the store loaded."},"unavailable":{"type":"string","description":"Set only when the store failed to load: short reason (≤140 chars)."}},"additionalProperties":true,"required":["count"],"description":"Facebook lead-form store: rows contributed, or why it was unavailable."},"manual":{"type":"object","properties":{"count":{"type":"integer","description":"Rows read from this store (0 when unavailable)."},"unavailable":{"type":"string","description":"Set only when the store failed to load: short reason (≤140 chars)."}},"additionalProperties":true,"required":["count"],"description":"Manual / CSV-import store: rows contributed, or why it was unavailable."},"landing_page":{"type":"object","properties":{"count":{"type":"integer","description":"Rows read from this store (0 when unavailable)."},"unavailable":{"type":"string","description":"Set only when the store failed to load: short reason (≤140 chars)."}},"additionalProperties":true,"required":["count"],"description":"Landing-page submission store: rows contributed, or why it was unavailable."}},"additionalProperties":true,"required":["facebook","manual","landing_page"],"description":"Which lead stores contributed to the working set; a failed store reports `unavailable` rather than under-counting."}},"additionalProperties":true,"required":["ok","requestId","staleAfterDays","leads","pagination","sources"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/leads/followup":{"get":{"operationId":"list_leads_requiring_followup","summary":"Open leads with a concrete reason to act right now: an overdue CRM task, or a New lead that has sat uncontacted longer than `newLeadHours` (default 24)","description":"Open leads with a concrete reason to act right now: an overdue CRM task, or a New lead that has sat uncontacted longer than `newLeadHours` (default 24). Each row says which reason applies. This reflects what humans recorded — it does not invent a scoring model.\n\nRequired scope: `leads.read`. Risk level: `read`.","tags":["leads"],"security":[{"bearerAuth":["leads.read"]}],"parameters":[{"name":"newLeadHours","in":"query","required":false,"description":"How long a New lead may sit before it counts as needing contact.","schema":{"type":"integer","minimum":1,"maximum":720,"default":24}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"leads":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Lead id; source-specific (Facebook lead id, manual _id or landing-page submission id)."},"source":{"type":"string","enum":["facebook","manual","landing_page"],"description":"Which store the lead came from."},"name":{"type":"string","description":"Full name (\"\" when unknown)."},"email":{"type":"string","description":"Email, lower-cased (\"\" when unknown)."},"phone":{"type":"string","description":"Phone as entered (\"\" when unknown)."},"status":{"type":"string","description":"Pipeline status; normally one of get_workspace_info.leadStatuses (default \"New\")."},"rating":{"type":"number","description":"Human-set rating (0 when unrated)."},"owner":{"type":"string","description":"Assigned owner (email or name, \"\" when unassigned)."},"dueDate":{"type":"string","description":"The board's Due Date (yyyy-mm-dd), \"\" when none is set."},"score":{"type":"number","description":"Lead score 0-100 from the hourly scoring sweep; absent when not scored yet."},"scoreBand":{"type":"string","enum":["hot","warm","cold","won","lost"],"description":"Score band; absent when not scored yet."},"createdAt":{"type":"string","description":"ISO 8601 creation time (\"\" when unknown)."},"updatedAt":{"type":"string","description":"ISO 8601 time of the last human edit/note, else createdAt."},"campaignName":{"type":"string","description":"Ad campaign / UTM campaign name (\"\" when none)."},"formName":{"type":"string","description":"Lead form name (\"Landing page\" for LP leads, \"\" when none)."},"pageName":{"type":"string","description":"Facebook page or landing-page name (\"\" when none)."},"platform":{"type":"string","description":"Origin platform, e.g. facebook, instagram, manual, landing_page."},"isOrganic":{"type":"boolean","description":"True when the lead did not come from a paid click."},"hasNote":{"type":"boolean","description":"True when the lead carries at least one note (edit layer or CRM)."},"reason":{"type":"string","enum":["overdue_task","never_contacted"],"description":"Why the lead needs follow-up."},"overdueTask":{"type":["object","null"],"properties":{"id":{"type":"string","description":"Task id."},"title":{"type":"string","description":"Task title."},"dueDate":{"type":"string","description":"Due date YYYY-MM-DD."}},"additionalProperties":true,"required":["title","dueDate"],"description":"The overdue task when reason is overdue_task, else null."}},"additionalProperties":true,"required":["id","source","name","email","phone","status","rating","owner","dueDate","createdAt","updatedAt","campaignName","formName","pageName","platform","isOrganic","hasNote","reason","overdueTask"]},"description":"Open leads with a concrete reason to act; overdue tasks first."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (max 100)."},"total":{"type":"integer","description":"Total matching rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the (already filtered and sorted) result set."},"sources":{"type":"object","properties":{"facebook":{"type":"object","properties":{"count":{"type":"integer","description":"Rows read from this store (0 when unavailable)."},"stale":{"type":"boolean","description":"True when the cached form leads are stale; only present when the store loaded."},"unavailable":{"type":"string","description":"Set only when the store failed to load: short reason (≤140 chars)."}},"additionalProperties":true,"required":["count"],"description":"Facebook lead-form store: rows contributed, or why it was unavailable."},"manual":{"type":"object","properties":{"count":{"type":"integer","description":"Rows read from this store (0 when unavailable)."},"unavailable":{"type":"string","description":"Set only when the store failed to load: short reason (≤140 chars)."}},"additionalProperties":true,"required":["count"],"description":"Manual / CSV-import store: rows contributed, or why it was unavailable."},"landing_page":{"type":"object","properties":{"count":{"type":"integer","description":"Rows read from this store (0 when unavailable)."},"unavailable":{"type":"string","description":"Set only when the store failed to load: short reason (≤140 chars)."}},"additionalProperties":true,"required":["count"],"description":"Landing-page submission store: rows contributed, or why it was unavailable."}},"additionalProperties":true,"required":["facebook","manual","landing_page"],"description":"Which lead stores contributed to the working set; a failed store reports `unavailable` rather than under-counting."},"newLeadHours":{"type":"integer","description":"Hours after which an uncontacted \"New\" lead counts (1-720, default 24)."}},"additionalProperties":true,"required":["ok","requestId","leads","pagination","sources","newLeadHours"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/contacts":{"get":{"operationId":"search_contacts","summary":"Search PEOPLE rather than submissions: lead records are merged by email (then phone), so someone who filled in three forms is one contact with three leads","description":"Search PEOPLE rather than submissions: lead records are merged by email (then phone), so someone who filled in three forms is one contact with three leads. Each contact carries company, status, owner, rating, the board's Due Date (dueDate, \"\" when none), the lists they are on and their records. Use search_leads for individual submissions, list_contacts_in_list to page through one list.\n\nRequired scope: `contacts.read`. Risk level: `read`.","tags":["contacts"],"security":[{"bearerAuth":["contacts.read"]}],"parameters":[{"name":"query","in":"query","required":false,"description":"Free text: name, email or phone.","schema":{"type":"string","maxLength":120}},{"name":"status","in":"query","required":false,"description":"Status of their most recent lead.","schema":{"type":"string","enum":["New","Contacted","Qualified","Scheduled a Meeting","Proposal","Negotiation","Won","Lost","Unresponsive"]}},{"name":"owner","in":"query","required":false,"description":"Assigned owner, exact match.","schema":{"type":"string","maxLength":120}},{"name":"dateFrom","in":"query","required":false,"description":"Only records at or after this ISO 8601 date/datetime (e.g. 2026-07-01).","schema":{"type":"string","maxLength":40}},{"name":"dateTo","in":"query","required":false,"description":"Only records at or before this ISO 8601 date/datetime.","schema":{"type":"string","maxLength":40}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"contacts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Contact key: \"e:<email>\", \"p:<digits>\" or \"l:<leadId>\"."},"name":{"type":"string","description":"Name (\"\" when unknown)."},"email":{"type":"string","description":"Lower-cased email (\"\" when unknown)."},"phone":{"type":"string","description":"Phone (\"\" when unknown)."},"company":{"type":"string","description":"Company (\"\" when unknown)."},"status":{"type":"string","description":"Status of the most recent record."},"owner":{"type":"string","description":"Owner of the newest record (\"\" when unassigned)."},"rating":{"type":"number","description":"Rating of the newest record."},"dueDate":{"type":"string","description":"The contact's Due Date (newest record's, else the first set), \"\" when none."},"primaryLeadId":{"type":"string","description":"Id of the newest record — what update_contact changes when given the contact id."},"firstSeen":{"type":"string","description":"ISO 8601 of the oldest record."},"lastSeen":{"type":"string","description":"ISO 8601 of the newest record."},"updatedAt":{"type":"string","description":"ISO 8601 of the most recent update across records."},"leadIds":{"type":"array","items":{"type":"string"},"description":"Up to 25 record ids behind this contact."},"sources":{"type":"array","items":{"type":"string","enum":["facebook","manual","landing_page"]},"description":"Distinct sources behind this contact."},"leadCount":{"type":"integer","description":"Total records merged into this contact."},"lists":{"type":"array","items":{"type":"string"},"description":"Union of My Lists across the records."},"records":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Record id — the stable contactId used by the Contacts table, My Lists and update_contact."},"source":{"type":"string","enum":["facebook","manual","landing_page"],"description":"Store the record lives in."},"name":{"type":"string","description":"Name (\"\" when unknown)."},"email":{"type":"string","description":"Lower-cased email (\"\" when unknown)."},"phone":{"type":"string","description":"Phone (\"\" when unknown)."},"company":{"type":"string","description":"Company (\"\" when unknown)."},"status":{"type":"string","description":"Pipeline status."},"owner":{"type":"string","description":"Owner email (\"\" when unassigned)."},"rating":{"type":"number","description":"Rating 0-5."},"dueDate":{"type":"string","description":"The board's Due Date (yyyy-mm-dd), \"\" when none is set."},"createdAt":{"type":"string","description":"ISO 8601 creation time."},"updatedAt":{"type":"string","description":"ISO 8601 last update."},"lists":{"type":"array","items":{"type":"string"},"description":"Names of the My Lists this record is on."},"hasNote":{"type":"boolean","description":"True when the record carries a note."}},"additionalProperties":true,"required":["id","source","name","email","phone","company","status","owner","rating","dueDate","createdAt","updatedAt","lists"],"description":"One underlying record of the contact."},"description":"Up to 25 underlying records, newest first."}},"additionalProperties":true,"required":["id","name","email","phone","company","status","owner","rating","dueDate","primaryLeadId","firstSeen","lastSeen","updatedAt","leadIds","sources","leadCount","lists","records"]},"description":"Matching contacts, most recently seen first."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (max 100)."},"total":{"type":"integer","description":"Total matching rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the (already filtered and sorted) result set."},"sources":{"type":"object","properties":{"facebook":{"type":"object","properties":{"count":{"type":"integer","description":"Rows read from this store (0 when unavailable)."},"stale":{"type":"boolean","description":"True when the cached form leads are stale; only present when the store loaded."},"unavailable":{"type":"string","description":"Set only when the store failed to load: short reason (≤140 chars)."}},"additionalProperties":true,"required":["count"],"description":"Facebook lead-form store: rows contributed, or why it was unavailable."},"manual":{"type":"object","properties":{"count":{"type":"integer","description":"Rows read from this store (0 when unavailable)."},"unavailable":{"type":"string","description":"Set only when the store failed to load: short reason (≤140 chars)."}},"additionalProperties":true,"required":["count"],"description":"Manual / CSV-import store: rows contributed, or why it was unavailable."},"landing_page":{"type":"object","properties":{"count":{"type":"integer","description":"Rows read from this store (0 when unavailable)."},"unavailable":{"type":"string","description":"Set only when the store failed to load: short reason (≤140 chars)."}},"additionalProperties":true,"required":["count"],"description":"Landing-page submission store: rows contributed, or why it was unavailable."}},"additionalProperties":true,"required":["facebook","manual","landing_page"],"description":"Which lead stores contributed to the working set; a failed store reports `unavailable` rather than under-counting."}},"additionalProperties":true,"required":["ok","requestId","contacts","pagination","sources"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/contacts/lookup":{"get":{"operationId":"get_contact","summary":"One contact with everything the CRM holds: identity, company, status, owner, rating, the board's Due Date (dueDate, \"\" when none is set), the lists they are on, every underlying record (each with its own dueDate/status/owner/lists — records[0] is the newest and is what update_contact changes), CRM notes and tasks, and a WhatsApp summary (connected? outreach sent? reply received?)","description":"One contact with everything the CRM holds: identity, company, status, owner, rating, the board's Due Date (dueDate, \"\" when none is set), the lists they are on, every underlying record (each with its own dueDate/status/owner/lists — records[0] is the newest and is what update_contact changes), CRM notes and tasks, and a WhatsApp summary (connected? outreach sent? reply received?). Address by contactId / record id, a contact id from search_contacts, email or phone.\n\nRequired scope: `contacts.read`. Risk level: `read`.","tags":["contacts"],"security":[{"bearerAuth":["contacts.read"]}],"parameters":[{"name":"id","in":"query","required":false,"description":"contactId / record id (from list_contacts_in_list or search_leads) or a contact id from search_contacts.","schema":{"type":"string","maxLength":200}},{"name":"email","in":"query","required":false,"description":"Email address.","schema":{"type":"string","maxLength":160}},{"name":"phone","in":"query","required":false,"description":"Phone number in any format.","schema":{"type":"string","maxLength":60}},{"name":"includeWhatsapp","in":"query","required":false,"description":"false to skip the WhatsApp summary (faster).","schema":{"type":"boolean","default":true}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"contact":{"type":"object","properties":{"id":{"type":"string","description":"Contact key: \"e:<email>\", \"p:<digits>\" or \"l:<leadId>\"."},"name":{"type":"string","description":"Name (\"\" when unknown)."},"email":{"type":"string","description":"Lower-cased email (\"\" when unknown)."},"phone":{"type":"string","description":"Phone (\"\" when unknown)."},"company":{"type":"string","description":"Company (\"\" when unknown)."},"status":{"type":"string","description":"Status of the most recent record."},"owner":{"type":"string","description":"Owner of the newest record (\"\" when unassigned)."},"rating":{"type":"number","description":"Rating of the newest record."},"dueDate":{"type":"string","description":"The contact's Due Date (newest record's, else the first set), \"\" when none."},"primaryLeadId":{"type":"string","description":"Id of the newest record — what update_contact changes when given the contact id."},"firstSeen":{"type":"string","description":"ISO 8601 of the oldest record."},"lastSeen":{"type":"string","description":"ISO 8601 of the newest record."},"updatedAt":{"type":"string","description":"ISO 8601 of the most recent update across records."},"leadIds":{"type":"array","items":{"type":"string"},"description":"Up to 25 record ids behind this contact."},"sources":{"type":"array","items":{"type":"string","enum":["facebook","manual","landing_page"]},"description":"Distinct sources behind this contact."},"leadCount":{"type":"integer","description":"Total records merged into this contact."},"lists":{"type":"array","items":{"type":"string"},"description":"Union of My Lists across the records."},"records":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Record id — the stable contactId used by the Contacts table, My Lists and update_contact."},"source":{"type":"string","enum":["facebook","manual","landing_page"],"description":"Store the record lives in."},"name":{"type":"string","description":"Name (\"\" when unknown)."},"email":{"type":"string","description":"Lower-cased email (\"\" when unknown)."},"phone":{"type":"string","description":"Phone (\"\" when unknown)."},"company":{"type":"string","description":"Company (\"\" when unknown)."},"status":{"type":"string","description":"Pipeline status."},"owner":{"type":"string","description":"Owner email (\"\" when unassigned)."},"rating":{"type":"number","description":"Rating 0-5."},"dueDate":{"type":"string","description":"The board's Due Date (yyyy-mm-dd), \"\" when none is set."},"createdAt":{"type":"string","description":"ISO 8601 creation time."},"updatedAt":{"type":"string","description":"ISO 8601 last update."},"lists":{"type":"array","items":{"type":"string"},"description":"Names of the My Lists this record is on."},"hasNote":{"type":"boolean","description":"True when the record carries a note."}},"additionalProperties":true,"required":["id","source","name","email","phone","company","status","owner","rating","dueDate","createdAt","updatedAt","lists"],"description":"One underlying record of the contact."},"description":"Up to 25 underlying records, newest first."},"notes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Note id."},"text":{"type":"string","description":"Note body (≤2000 chars)."},"kind":{"type":"string","description":"Note kind, e.g. note, call, meeting (\"\" when unset)."},"author":{"type":"string","description":"Author email (\"\" when unknown)."},"createdAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."},"leadId":{"type":"string","description":"Record the note hangs off."}},"additionalProperties":true,"required":["id","text","kind","author","createdAt"]},"description":"Up to 50 CRM notes across the records, newest first (each with leadId)."},"tasks":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"Task (see get_task) plus leadId."},"description":"Up to 20 CRM tasks attached to the records."},"hasNote":{"type":"boolean","description":"True when any note exists."},"whatsapp":{"type":"object","properties":{"channelConnected":{"type":["boolean","null"],"description":"true/false; null when it could not be determined or the contact has no phone."},"inbound":{"type":"integer","description":"Messages received from the contact (visible window)."},"outbound":{"type":"integer","description":"Messages sent to the contact (visible window)."},"lastInboundAt":{"type":"string","description":"ISO 8601 of the last reply, \"\" when none."},"lastOutboundAt":{"type":"string","description":"ISO 8601 of the last outreach, \"\" when none."},"hasOutreach":{"type":"boolean","description":"At least one outbound message exists."},"hasReply":{"type":"boolean","description":"At least one inbound message exists."},"partial":{"type":"boolean","description":"History window is capped; older messages may exist."},"note":{"type":"string","description":"Explicit caveats (not connected, partial, no phone…)."}},"additionalProperties":true,"description":"WhatsApp summary for the contact."}},"additionalProperties":true,"required":["id","name","email","phone","company","status","owner","rating","dueDate","primaryLeadId","firstSeen","lastSeen","updatedAt","leadIds","sources","leadCount","lists","records","notes","tasks","whatsapp"],"description":"The contact with CRM detail."}},"additionalProperties":true,"required":["ok","requestId","contact"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/contacts/activity":{"get":{"operationId":"get_contact_activity","summary":"Behavioural timeline for one person: site page views, cart events and purchases, plus channel touches (email opens/clicks, SMS clicks, landing-page and on-site interactions), with the engagement score and order totals the platform already computes","description":"Behavioural timeline for one person: site page views, cart events and purchases, plus channel touches (email opens/clicks, SMS clicks, landing-page and on-site interactions), with the engagement score and order totals the platform already computes. Identify them by email or phone. Use it to answer \"what has this person actually done?\".\n\nRequired scope: `contacts.read`. Risk level: `read`.","tags":["contacts"],"security":[{"bearerAuth":["contacts.read"]}],"parameters":[{"name":"email","in":"query","required":false,"description":"Email address.","schema":{"type":"string","maxLength":160}},{"name":"phone","in":"query","required":false,"description":"Phone number in any format.","schema":{"type":"string","maxLength":60}},{"name":"limit","in":"query","required":false,"description":"Maximum events to return.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"contact":{"type":"object","properties":{"email":{"type":"string","description":"Lower-cased email (\"\" when addressed by phone)."},"phone":{"type":"string","description":"Phone digits (\"\" when addressed by email)."}},"additionalProperties":true,"required":["email","phone"],"description":"The identifier the timeline was resolved for."},"notes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Note id."},"text":{"type":"string","description":"Note body (≤2000 chars)."},"kind":{"type":"string","description":"Note kind, e.g. note, call, meeting (\"\" when unset)."},"author":{"type":"string","description":"Author email (\"\" when unknown)."},"createdAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."}},"additionalProperties":true,"required":["id","text","kind","author","createdAt"]},"description":"Up to 50 CRM notes on the matching lead (empty when none / no lead match)."},"summary":{"type":["object","null"],"properties":{"orders":{"type":"integer","description":"Orders attributed to this contact."},"totalSpend":{"type":"number","description":"Total order value in `currency`."},"currency":{"type":"string","description":"Currency code (\"\" when unknown)."},"engagementScore":{"type":"number","description":"Engagement score as shown in the app."},"lastOrderAt":{"type":"string","description":"ISO 8601 of the last order (\"\" when none)."}},"additionalProperties":true,"required":["orders","totalSpend","currency","engagementScore","lastOrderAt"],"description":"Engagement summary from site + channel events; null when none."},"events":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","description":"Event type, e.g. pageview, cart, purchase, email_open."},"at":{"type":"string","description":"ISO 8601 (\"\" when unknown)."},"channel":{"type":"string","description":"Channel / source (\"\" when unknown)."},"url":{"type":"string","description":"Page URL when the event has one (\"\" otherwise)."},"value":{"type":["number","null"],"description":"Order total or event value; null when none."}},"additionalProperties":true,"required":["type","at","channel","url","value"]},"description":"Individual events, newest first, up to `limit` (max 100)."}},"additionalProperties":true,"required":["ok","requestId","contact","notes","summary","events"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/contacts/lists":{"get":{"operationId":"list_contact_lists","summary":"The Leads board's named contact lists (\"My Lists\", e","description":"The Leads board's named contact lists (\"My Lists\", e.g. \"FORTVISION Sales CRM\") with their ids, names and sizes. memberCount = ids stored on the list; visibleCount = members that resolve to a record this token can see (the number the app shows). Pass the id (or the exact name) to list_contacts_in_list. Landing-page lists are a different thing: list_landing_page_lists.\n\nRequired scope: `contacts.read`. Risk level: `read`.","tags":["contacts"],"security":[{"bearerAuth":["contacts.read"]}],"parameters":[{"name":"query","in":"query","required":false,"description":"Filter by name (substring).","schema":{"type":"string","maxLength":120}},{"name":"group","in":"query","required":false,"description":"Only lists of this kind.","schema":{"type":"string","enum":["my_list","linkedin","linkedin_ads","wallet","tiktok","calls"]}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"lists":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"List id, \"ml:<name>\" — pass to list_contacts_in_list."},"name":{"type":"string","description":"List name as shown in the app."},"group":{"type":"string","enum":["my_list","linkedin","linkedin_ads","wallet","tiktok","calls"],"description":"Rail section the list belongs to."},"memberCount":{"type":"integer","description":"Ids stored on the list."},"visibleCount":{"type":"integer","description":"Members that resolve to a record this token can see (the app's count)."},"movedToAnotherWorkspace":{"type":"boolean","description":"True when the list was moved to another workspace (the app hides it)."}},"additionalProperties":true,"required":["id","name","group","memberCount","visibleCount","movedToAnotherWorkspace"]},"description":"Lists, largest first."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (max 100)."},"total":{"type":"integer","description":"Total matching rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the (already filtered and sorted) result set."},"totalLists":{"type":"integer","description":"Lists matching the filters."}},"additionalProperties":true,"required":["ok","requestId","lists","pagination","totalLists"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"create_contact_list","summary":"Create an empty My List on the Leads board","description":"Create an empty My List on the Leads board. If a list with that name exists it is returned unchanged (created:false). Then add members with add_contacts_to_list.\n\nRequired scope: `contacts.write`. Risk level: `write`.","tags":["contacts"],"security":[{"bearerAuth":["contacts.write"]}],"parameters":[{"name":"name","in":"query","required":true,"description":"List name as it should appear in the app.","schema":{"type":"string","maxLength":120}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"created":{"type":"boolean","description":"true when a new list was created; false when the name already existed."},"list":{"type":"object","properties":{"id":{"type":"string","description":"ml:<name>."},"name":{"type":"string","description":"Name."},"memberCount":{"type":"integer","description":"Members."}},"additionalProperties":true,"required":["id","name","memberCount"],"description":"The list."},"targetType":{"type":"string","enum":["contact_list"],"description":"Always contact_list."},"targetId":{"type":"string","description":"List id."},"verified":{"type":"boolean","description":"Read back after saving."},"message":{"type":"string","description":"Set when the list already existed."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","created","list","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/contacts/lists/{listId}/contacts":{"get":{"operationId":"list_contacts_in_list","summary":"Every contact on ONE list, paginated, in list order (newest members first)","description":"Every contact on ONE list, paginated, in list order (newest members first). Each row carries the stable contactId (the record id the Contacts table and update_contact use), the lists it belongs to, name, email, phone, company, status, owner, rating, dueDate (\"\" when none), createdAt and updatedAt. total (list.memberCount) is the stored membership; members whose record is not visible to this token are counted in notVisible, never mixed in from other lists. Filters narrow the page, never the membership.\n\nRequired scope: `contacts.read`. Risk level: `read`.","tags":["contacts"],"security":[{"bearerAuth":["contacts.read"]}],"parameters":[{"name":"listId","in":"path","required":true,"description":"List id from list_contact_lists (\"ml:<name>\") or the exact list name.","schema":{"type":"string","maxLength":140}},{"name":"query","in":"query","required":false,"description":"Free text: name, email, company or phone.","schema":{"type":"string","maxLength":120}},{"name":"status","in":"query","required":false,"description":"Only this pipeline status.","schema":{"type":"string","enum":["New","Contacted","Qualified","Scheduled a Meeting","Proposal","Negotiation","Won","Lost","Unresponsive"]}},{"name":"owner","in":"query","required":false,"description":"Only this owner (email), exact match.","schema":{"type":"string","maxLength":120}},{"name":"hasDueDate","in":"query","required":false,"description":"true = only contacts with a Due Date set; false = only those without.","schema":{"type":"boolean"}},{"name":"dueBefore","in":"query","required":false,"description":"Only contacts whose Due Date is on or before this day (yyyy-mm-dd).","schema":{"type":"string","maxLength":10}},{"name":"dueAfter","in":"query","required":false,"description":"Only contacts whose Due Date is on or after this day (yyyy-mm-dd).","schema":{"type":"string","maxLength":10}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":100}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"list":{"type":"object","properties":{"id":{"type":"string","description":"List id."},"name":{"type":"string","description":"List name."},"memberCount":{"type":"integer","description":"Ids stored on the list (the total)."}},"additionalProperties":true,"required":["id","name","memberCount"],"description":"The list."},"contacts":{"type":"array","items":{"type":"object","properties":{"contactId":{"type":"string","description":"Stable record id — use with get_contact / update_contact."},"source":{"type":"string","enum":["facebook","manual","landing_page"],"description":"Store the record lives in."},"name":{"type":"string","description":"Name (\"\" when unknown)."},"email":{"type":"string","description":"Lower-cased email (\"\" when unknown)."},"phone":{"type":"string","description":"Phone (\"\" when unknown)."},"company":{"type":"string","description":"Company (\"\" when unknown)."},"status":{"type":"string","description":"Pipeline status."},"owner":{"type":"string","description":"Owner email (\"\" when unassigned)."},"rating":{"type":"number","description":"Rating 0-5."},"dueDate":{"type":"string","description":"The board's Due Date (yyyy-mm-dd), \"\" when none is set."},"createdAt":{"type":"string","description":"ISO 8601 creation time."},"updatedAt":{"type":"string","description":"ISO 8601 last update."},"lists":{"type":"array","items":{"type":"string"},"description":"Names of the My Lists this record is on."},"hasNote":{"type":"boolean","description":"True when the record carries a note."}},"additionalProperties":true,"required":["contactId","source","name","email","phone","company","status","owner","rating","dueDate","createdAt","updatedAt","lists"]},"description":"This page of members, in list order."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (max 100)."},"total":{"type":"integer","description":"Total matching rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the (already filtered and sorted) result set."},"matched":{"type":"integer","description":"Members visible to this token that pass the filters (what pagination counts)."},"notVisible":{"type":"integer","description":"Member ids with no visible record (deleted or outside the grant)."},"note":{"type":"string","description":"Present when notVisible > 0."}},"additionalProperties":true,"required":["ok","requestId","list","contacts","pagination","matched","notVisible"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/contacts/whatsapp":{"get":{"operationId":"get_contact_whatsapp_history","summary":"The WhatsApp thread with one contact — inbound and outbound messages with time, channel and text — from the workspace's business number and any QR-linked personal number","description":"The WhatsApp thread with one contact — inbound and outbound messages with time, channel and text — from the workspace's business number and any QR-linked personal number. Says explicitly whether WhatsApp is connected (channelConnected) and whether the history is partial, and summarises hasOutreach / hasReply so \"was this person already contacted, did they answer?\" has a definite answer. Address the contact by contactId / contact id, or by phone.\n\nRequired scope: `conversations.read`. Risk level: `read`.","tags":["conversations"],"security":[{"bearerAuth":["conversations.read"]}],"parameters":[{"name":"id","in":"query","required":false,"description":"contactId from list_contacts_in_list, a lead id, or a contact id from search_contacts.","schema":{"type":"string","maxLength":200}},{"name":"phone","in":"query","required":false,"description":"Alternatively the phone number, any format.","schema":{"type":"string","maxLength":60}},{"name":"limit","in":"query","required":false,"description":"Newest messages to return (max 200).","schema":{"type":"integer","minimum":1,"maximum":200,"default":100}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"contactId":{"type":"string","description":"Resolved record id when addressed by id."},"phone":{"type":"string","description":"Phone digits the thread was resolved for (\"\" when the contact has none)."},"channelConnected":{"type":["boolean","null"],"description":"true/false; null when undeterminable."},"messages":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string","description":"ISO 8601."},"direction":{"type":"string","enum":["inbound","outbound"],"description":"inbound = from the contact."},"channel":{"type":"string","enum":["whatsapp"],"description":"Always whatsapp."},"via":{"type":"string","description":"\"business\" (Cloud API number) or the personal number it went through."},"text":{"type":"string","description":"Message text (≤500 chars)."}},"additionalProperties":true,"required":["at","direction","channel","via","text"]},"description":"Oldest → newest, up to limit."},"counts":{"type":"object","properties":{"inbound":{"type":"integer","description":"From the contact."},"outbound":{"type":"integer","description":"To the contact."}},"additionalProperties":true,"required":["inbound","outbound"],"description":"Totals in the visible window."},"lastInboundAt":{"type":"string","description":"ISO 8601 of the last reply, \"\" when none."},"lastOutboundAt":{"type":"string","description":"ISO 8601 of the last outreach, \"\" when none."},"hasOutreach":{"type":"boolean","description":"At least one outbound message."},"hasReply":{"type":"boolean","description":"At least one inbound message."},"partial":{"type":"boolean","description":"True when the window is capped and older messages may exist."},"note":{"type":"string","description":"Explicit caveats: not connected, partial history, no phone, nothing found."}},"additionalProperties":true,"required":["ok","requestId","phone","channelConnected","messages","counts","lastInboundAt","lastOutboundAt","hasOutreach","hasReply","partial"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/contacts/lists/{listId}/add":{"post":{"operationId":"add_contacts_to_list","summary":"Add contact records to a My List by their record ids (contactId / lead id)","description":"Add contact records to a My List by their record ids (contactId / lead id). Every id must be a record this token can see — an unknown id refuses the whole call and nothing is changed. Records already on the list are counted as alreadyMembers. Membership is read back after saving (verified). Up to 1000 ids per call.\n\nRequired scope: `contacts.write`. Risk level: `write`.","tags":["contacts"],"security":[{"bearerAuth":["contacts.write"]}],"parameters":[{"name":"listId","in":"path","required":true,"description":"List id (\"ml:<name>\") or exact name.","schema":{"type":"string","maxLength":140}},{"name":"contactIds","in":"query","required":true,"description":"Record ids to add.","schema":{"type":"array","maxItems":1000,"items":{"type":"string"}}},{"name":"createIfMissing","in":"query","required":false,"description":"true = create the list when it does not exist (default false).","schema":{"type":"boolean"}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["contact_list"],"description":"Always contact_list."},"targetId":{"type":"string","description":"List id."},"list":{"type":"object","properties":{"id":{"type":"string","description":"ml:<name>."},"name":{"type":"string","description":"Name."},"memberCount":{"type":"integer","description":"Members now."}},"additionalProperties":true,"required":["id","name","memberCount"],"description":"The list after the change."},"added":{"type":"integer","description":"Ids newly added."},"alreadyMembers":{"type":"integer","description":"Ids that were already on the list."},"verified":{"type":"boolean","description":"Every id is on the list after read-back."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","list","added","alreadyMembers","verified"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/contacts/lists/{listId}/remove":{"post":{"operationId":"remove_contacts_from_list","summary":"Remove contact records from a My List (the records themselves are untouched and stay on the board)","description":"Remove contact records from a My List (the records themselves are untouched and stay on the board). For records that were imported INTO this list, the list tag on the record is cleared too (tagsCleared) so the board does not re-add them. Reversible with add_contacts_to_list.\n\nRequired scope: `contacts.write`. Risk level: `write`.","tags":["contacts"],"security":[{"bearerAuth":["contacts.write"]}],"parameters":[{"name":"listId","in":"path","required":true,"description":"List id (\"ml:<name>\") or exact name.","schema":{"type":"string","maxLength":140}},{"name":"contactIds","in":"query","required":true,"description":"Record ids to remove.","schema":{"type":"array","maxItems":1000,"items":{"type":"string"}}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["contact_list"],"description":"Always contact_list."},"targetId":{"type":"string","description":"List id."},"list":{"type":"object","properties":{"id":{"type":"string","description":"ml:<name>."},"name":{"type":"string","description":"Name."},"memberCount":{"type":"integer","description":"Members now."}},"additionalProperties":true,"required":["id","name","memberCount"],"description":"The list after the change."},"removed":{"type":"integer","description":"Ids removed."},"notMembers":{"type":"integer","description":"Ids that were not on the list."},"tagsCleared":{"type":"integer","description":"Imported/landing-page records whose list tag was cleared so the board does not re-add them."},"tagErrors":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Records whose tag could not be cleared."},"verified":{"type":"boolean","description":"No id remains on the list after read-back."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","list","removed","notMembers","tagsCleared","verified"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/contacts/lists/{listId}/delete":{"post":{"operationId":"delete_contact_list","summary":"Delete a My List (lists of up to 500 members; larger ones only in the app)","description":"Delete a My List (lists of up to 500 members; larger ones only in the app). Member records are NOT deleted. PREVIEW FIRST: without confirm it reports the list, its size and how many imported records carry its tag (cleared on delete so the list does not resurrect).\n\nRequired scope: `records.delete`. Risk level: `high`.","tags":["records"],"security":[{"bearerAuth":["records.delete"]}],"parameters":[{"name":"listId","in":"path","required":true,"description":"List id (\"ml:<name>\") or exact name.","schema":{"type":"string","maxLength":140}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"action":{"type":"string","description":"Preview only."},"list":{"type":"object","properties":{"id":{"type":"string","description":"ml:<name>."},"name":{"type":"string","description":"Name."},"memberCount":{"type":"integer","description":"Members."}},"additionalProperties":true,"description":"Preview: the list and its size."},"taggedRecords":{"type":"integer","description":"Preview: records carrying this list's tag."},"warnings":{"type":"array","items":{"type":"string"},"description":"Preview warnings."},"deleted":{"type":"boolean","description":"Run: the list is gone."},"name":{"type":"string","description":"Run: the deleted list name."},"formerMembers":{"type":"integer","description":"Run: how many members it had (records untouched)."},"tagsCleared":{"type":"integer","description":"Run: record tags cleared."},"verified":{"type":"boolean","description":"Run: read back — the list no longer exists."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."},"targetType":{"type":"string","description":"Kind of record the action targets."},"targetId":{"type":"string","description":"Id of the record the action targets."}},"additionalProperties":true,"required":["ok","requestId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/contacts/{id}/update":{"post":{"operationId":"update_contact","summary":"Update ONE existing contact record by its stable id: the board's Due Date (dueDate, a calendar day — \"\" clears it; this is the contact's own date, not a task due date), pipeline status, owner, rating, name / email / phone / company (not for Facebook leads), and/or add a note","description":"Update ONE existing contact record by its stable id: the board's Due Date (dueDate, a calendar day — \"\" clears it; this is the contact's own date, not a task due date), pipeline status, owner, rating, name / email / phone / company (not for Facebook leads), and/or add a note. Only the fields you pass change. Fails with not_found for an unknown id and NEVER creates a record (use create_lead / import_contacts for that). Pass dryRun:true to preview before/after without writing. After writing, the record is read back and \"verified\" reports whether the store now shows the new values.\n\nRequired scope: `contacts.write`. Risk level: `write`.","tags":["contacts"],"security":[{"bearerAuth":["contacts.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"contactId from list_contacts_in_list (= the lead/record id), or a contact id from search_contacts (its newest record is updated).","schema":{"type":"string","maxLength":200}},{"name":"dueDate","in":"query","required":false,"description":"Due Date as yyyy-mm-dd, or \"\" to clear.","schema":{"type":"string","maxLength":40}},{"name":"status","in":"query","required":false,"description":"New pipeline status.","schema":{"type":"string","enum":["New","Contacted","Qualified","Scheduled a Meeting","Proposal","Negotiation","Won","Lost","Unresponsive"]}},{"name":"owner","in":"query","required":false,"description":"New owner (their email), or \"\" to unassign.","schema":{"type":"string","maxLength":120}},{"name":"rating","in":"query","required":false,"description":"Star rating, 0-5.","schema":{"type":"integer","minimum":0,"maximum":5}},{"name":"name","in":"query","required":false,"description":"New full name (manual and landing-page/imported records only).","schema":{"type":"string","maxLength":160}},{"name":"email","in":"query","required":false,"description":"New email (manual and landing-page/imported records only). Changes the contact's identity key.","schema":{"type":"string","maxLength":160}},{"name":"phone","in":"query","required":false,"description":"New phone (manual and landing-page/imported records only).","schema":{"type":"string","maxLength":60}},{"name":"company","in":"query","required":false,"description":"New company (landing-page/imported records only).","schema":{"type":"string","maxLength":160}},{"name":"note","in":"query","required":false,"description":"A note to add to the contact's timeline.","schema":{"type":"string","maxLength":5000}},{"name":"noteKind","in":"query","required":false,"description":"What the note records (default note).","schema":{"type":"string","enum":["note","call","email","meeting","linkedin","sms","other"]}},{"name":"dryRun","in":"query","required":false,"description":"true = report before/after and change nothing.","schema":{"type":"boolean"}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["contact"],"description":"Always contact."},"targetId":{"type":"string","description":"The record id that was (or would be) changed."},"contactId":{"type":"string","description":"Same as targetId — the stable record id."},"contact":{"type":"object","properties":{"id":{"type":"string","description":"Contact key."},"name":{"type":"string","description":"Name."},"email":{"type":"string","description":"Email."},"phone":{"type":"string","description":"Phone."},"records":{"type":"integer","description":"Records behind the contact."}},"additionalProperties":true,"required":["id","name","email","phone","records"],"description":"Identity of the merged contact."},"source":{"type":"string","enum":["facebook","manual","landing_page"],"description":"Store the record lives in."},"lists":{"type":"array","items":{"type":"string"},"description":"My Lists the record is on."},"before":{"type":"object","properties":{"dueDate":{"type":"string","description":"yyyy-mm-dd, \"\" when none."},"status":{"type":"string","description":"Pipeline status."},"owner":{"type":"string","description":"Owner email, \"\" when unassigned."},"rating":{"type":"number","description":"Rating 0-5."},"name":{"type":"string","description":"Full name."},"email":{"type":"string","description":"Email."},"phone":{"type":"string","description":"Phone."},"company":{"type":"string","description":"Company."}},"additionalProperties":true,"required":["dueDate","status","owner","rating"],"description":"Contact record fields (Due Date, status, owner, rating)."},"after":{"type":"object","properties":{"dueDate":{"type":"string","description":"yyyy-mm-dd, \"\" when none."},"status":{"type":"string","description":"Pipeline status."},"owner":{"type":"string","description":"Owner email, \"\" when unassigned."},"rating":{"type":"number","description":"Rating 0-5."},"name":{"type":"string","description":"Full name."},"email":{"type":"string","description":"Email."},"phone":{"type":"string","description":"Phone."},"company":{"type":"string","description":"Company."}},"additionalProperties":true,"required":["dueDate","status","owner","rating"],"description":"Contact record fields (Due Date, status, owner, rating)."},"changed":{"type":"array","items":{"type":"string","enum":["dueDate","status","owner","rating","name","email","phone","company"]},"description":"Fields that differ between before and after."},"preview":{"type":"boolean","description":"true on a dryRun."},"updated":{"type":"boolean","description":"true when a field was written (false on dryRun or when nothing differed)."},"verified":{"type":["boolean","null"],"description":"After writing: the record was read back and shows the new values. null on dryRun."},"readBack":{"type":["object","null"],"properties":{"dueDate":{"type":"string","description":"yyyy-mm-dd, \"\" when none."},"status":{"type":"string","description":"Pipeline status."},"owner":{"type":"string","description":"Owner email, \"\" when unassigned."},"rating":{"type":"number","description":"Rating 0-5."},"name":{"type":"string","description":"Full name."},"email":{"type":"string","description":"Email."},"phone":{"type":"string","description":"Phone."},"company":{"type":"string","description":"Company."},"updatedAt":{"type":"string","description":"ISO 8601."}},"additionalProperties":true,"required":["dueDate","status","owner","rating"],"description":"The record as re-read after the write (null on dryRun)."},"message":{"type":"string","description":"Dry-run explanation."},"noteWouldBeAdded":{"type":"string","description":"Dry run: the note text that would be added."},"note":{"type":"object","additionalProperties":true,"description":"The note added (id, kind, text, createdAt)."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","contactId","contact","source","lists","before","after","changed","updated"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/contacts/batch-update":{"post":{"operationId":"update_contacts_batch","summary":"Update up to 200 existing contact records in one call, each with its own fields (dueDate, status, owner, rating, name, email, phone, company, note)","description":"Update up to 200 existing contact records in one call, each with its own fields (dueDate, status, owner, rating, name, email, phone, company, note). PREVIEW FIRST: without confirm it resolves every id and reports before/after per contact and which ids do not exist. On confirm each record is written through the same path as update_contact, failures are reported per item without stopping the rest, nothing is ever created, and one read-back pass verifies every change. Fields not named on an item are left untouched.\n\nRequired scope: `contacts.write`. Risk level: `high`.","tags":["contacts"],"security":[{"bearerAuth":["contacts.write"]}],"parameters":[{"name":"updates","in":"query","required":true,"description":"Items: { id, dueDate?, status?, owner?, rating?, name?, email?, phone?, company?, note?, noteKind? }.","schema":{"type":"array","maxItems":200,"items":{"type":"object"}}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"action":{"type":"string","description":"Preview only: update_contacts_batch."},"total":{"type":"integer","description":"Items in the batch."},"found":{"type":"integer","description":"Preview: ids that resolve to a visible record."},"notFound":{"type":"integer","description":"Preview: ids with no visible record (nothing will be created)."},"invalid":{"type":"integer","description":"Preview: items with invalid values."},"willChange":{"type":"integer","description":"Preview: records that would change."},"unchanged":{"type":"integer","description":"Records whose supplied values already matched."},"warnings":{"type":"array","items":{"type":"string"},"description":"Preview warnings."},"updated":{"type":"integer","description":"Run: records written."},"failed":{"type":"integer","description":"Run: items that failed (see results[].error)."},"verified":{"type":"integer","description":"Run: written records whose read-back matched."},"mismatched":{"type":"integer","description":"Run: written records whose read-back did NOT match — investigate."},"message":{"type":"string","description":"Run summary."},"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The id as supplied."},"contactId":{"type":"string","description":"Resolved record id."},"found":{"type":"boolean","description":"Preview: resolved?"},"ok":{"type":"boolean","description":"Run: written (or already correct) without error."},"verified":{"type":"boolean","description":"Run: read-back matched."},"source":{"type":"string","description":"Store of the record."},"email":{"type":"string","description":"Record email."},"before":{"type":"object","properties":{"dueDate":{"type":"string","description":"yyyy-mm-dd, \"\" when none."},"status":{"type":"string","description":"Pipeline status."},"owner":{"type":"string","description":"Owner email, \"\" when unassigned."},"rating":{"type":"number","description":"Rating 0-5."},"name":{"type":"string","description":"Full name."},"email":{"type":"string","description":"Email."},"phone":{"type":"string","description":"Phone."},"company":{"type":"string","description":"Company."}},"additionalProperties":true,"required":["dueDate","status","owner","rating"],"description":"Contact record fields (Due Date, status, owner, rating)."},"after":{"type":"object","properties":{"dueDate":{"type":"string","description":"yyyy-mm-dd, \"\" when none."},"status":{"type":"string","description":"Pipeline status."},"owner":{"type":"string","description":"Owner email, \"\" when unassigned."},"rating":{"type":"number","description":"Rating 0-5."},"name":{"type":"string","description":"Full name."},"email":{"type":"string","description":"Email."},"phone":{"type":"string","description":"Phone."},"company":{"type":"string","description":"Company."}},"additionalProperties":true,"required":["dueDate","status","owner","rating"],"description":"Contact record fields (Due Date, status, owner, rating)."},"changed":{"type":"array","items":{"type":"string"},"description":"Fields that change."},"noteWouldBeAdded":{"type":"string","description":"Preview: note text."},"note":{"type":"string","description":"Run: id of the note added."},"error":{"type":"string","description":"Why this item failed (not_found: … / invalid_input: …)."}},"additionalProperties":true,"required":["id"]},"description":"One entry per item, in input order (preview and run)."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."},"targetType":{"type":"string","description":"Kind of record the action targets."},"targetId":{"type":"string","description":"Id of the record the action targets."}},"additionalProperties":true,"required":["ok","requestId","results"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/stores":{"get":{"operationId":"list_stores","summary":"The connected eCommerce stores/websites in this workspace (Shopify, WooCommerce, Wix, or GTM-connected sites)","description":"The connected eCommerce stores/websites in this workspace (Shopify, WooCommerce, Wix, or GTM-connected sites). Every customer tool needs a storeId from here.\n\nRequired scope: `customers.read`. Risk level: `read`.","tags":["customers"],"security":[{"bearerAuth":["customers.read"]}],"parameters":[{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"stores":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Store (site) id — pass as storeId to the customer tools."},"name":{"type":"string","description":"Store name (falls back to domain or id)."},"domain":{"type":"string","description":"Store domain (\"\" when unknown)."},"platform":{"type":"string","description":"Store platform, e.g. woocommerce, shopify, wix (\"\" when unknown)."},"productCount":{"type":"integer","description":"Products in the synced catalog."}},"additionalProperties":true,"required":["id","name","domain","platform","productCount"]},"description":"Connected eCommerce stores (sites) visible to this token."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (max 100)."},"total":{"type":"integer","description":"Total matching rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the (already filtered and sorted) result set."},"source":{"type":"string","description":"Backing store the list was read from (e.g. redis)."}},"additionalProperties":true,"required":["ok","requestId","stores","pagination","source"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/stores/{storeId}/customers":{"get":{"operationId":"search_customers","summary":"Customers of one store, aggregated from its orders: order count, lifetime spend, average order value, first and last order","description":"Customers of one store, aggregated from its orders: order count, lifetime spend, average order value, first and last order. Filter by minimum orders or a last-order date range; sort by recency (default) or spend.\n\nRequired scope: `customers.read`. Risk level: `read`.","tags":["customers"],"security":[{"bearerAuth":["customers.read"]}],"parameters":[{"name":"storeId","in":"path","required":true,"description":"Store id from list_stores.","schema":{"type":"string","maxLength":80}},{"name":"query","in":"query","required":false,"description":"Free text: email, name or phone.","schema":{"type":"string","maxLength":120}},{"name":"minOrders","in":"query","required":false,"description":"Only customers with at least this many orders.","schema":{"type":"integer","minimum":1,"maximum":1000}},{"name":"sort","in":"query","required":false,"description":"Result order.","schema":{"type":"string","enum":["recent_desc","spend_desc"],"default":"recent_desc"}},{"name":"dateFrom","in":"query","required":false,"description":"Only records at or after this ISO 8601 date/datetime (e.g. 2026-07-01).","schema":{"type":"string","maxLength":40}},{"name":"dateTo","in":"query","required":false,"description":"Only records at or before this ISO 8601 date/datetime.","schema":{"type":"string","maxLength":40}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"customers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Customer key: lower-cased email, or \"order:<id>\" for orders without one."},"email":{"type":"string","description":"Lower-cased email (\"\" when the order carried none)."},"name":{"type":"string","description":"Customer name (\"\" when unknown)."},"phone":{"type":"string","description":"Phone (\"\" when unknown)."},"orders":{"type":"integer","description":"Number of orders (within the 1000 most recent store orders)."},"totalSpend":{"type":"number","description":"Sum of order totals in `currency`, 2 decimals."},"currency":{"type":"string","description":"Currency of the first order seen (else store currency, \"\" when unknown)."},"firstOrderAt":{"type":"string","description":"ISO 8601 of the earliest order (\"\" when unknown)."},"lastOrderAt":{"type":"string","description":"ISO 8601 of the latest order (\"\" when unknown)."},"storeId":{"type":"string","description":"Store id the customer belongs to."},"avgOrderValue":{"type":"number","description":"totalSpend / orders, 2 decimals."}},"additionalProperties":true,"required":["id","email","name","phone","orders","totalSpend","currency","firstOrderAt","lastOrderAt","storeId","avgOrderValue"]},"description":"Matching customers (aggregated from orders)."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (max 100)."},"total":{"type":"integer","description":"Total matching rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the (already filtered and sorted) result set."},"storeId":{"type":"string","description":"The store searched."},"source":{"type":"string","description":"Backing store the orders were read from (e.g. redis)."},"note":{"type":"string","description":"Caveat from the orders read (e.g. capped), only when present."}},"additionalProperties":true,"required":["ok","requestId","customers","pagination","storeId","source"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/stores/{storeId}/customers/lookup":{"get":{"operationId":"get_customer","summary":"One customer of one store by email (or the id from search_customers), with their order totals and dates","description":"One customer of one store by email (or the id from search_customers), with their order totals and dates.\n\nRequired scope: `customers.read`. Risk level: `read`.","tags":["customers"],"security":[{"bearerAuth":["customers.read"]}],"parameters":[{"name":"storeId","in":"path","required":true,"description":"Store id from list_stores.","schema":{"type":"string","maxLength":80}},{"name":"email","in":"query","required":false,"description":"Customer email.","schema":{"type":"string","maxLength":160}},{"name":"id","in":"query","required":false,"description":"Customer id from search_customers.","schema":{"type":"string","maxLength":200}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"customer":{"type":"object","properties":{"id":{"type":"string","description":"Customer key: lower-cased email, or \"order:<id>\" for orders without one."},"email":{"type":"string","description":"Lower-cased email (\"\" when the order carried none)."},"name":{"type":"string","description":"Customer name (\"\" when unknown)."},"phone":{"type":"string","description":"Phone (\"\" when unknown)."},"orders":{"type":"integer","description":"Number of orders (within the 1000 most recent store orders)."},"totalSpend":{"type":"number","description":"Sum of order totals in `currency`, 2 decimals."},"currency":{"type":"string","description":"Currency of the first order seen (else store currency, \"\" when unknown)."},"firstOrderAt":{"type":"string","description":"ISO 8601 of the earliest order (\"\" when unknown)."},"lastOrderAt":{"type":"string","description":"ISO 8601 of the latest order (\"\" when unknown)."},"storeId":{"type":"string","description":"Store id the customer belongs to."},"avgOrderValue":{"type":"number","description":"totalSpend / orders, 2 decimals."}},"additionalProperties":true,"required":["id","email","name","phone","orders","totalSpend","currency","firstOrderAt","lastOrderAt","storeId","avgOrderValue"],"description":"The customer, aggregated from the store orders."}},"additionalProperties":true,"required":["ok","requestId","customer"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/stores/{storeId}/orders":{"get":{"operationId":"list_customer_orders","summary":"Recent orders of one customer in one store, newest first: number, status, total, items, coupons and dates","description":"Recent orders of one customer in one store, newest first: number, status, total, items, coupons and dates. Identify the customer by email, phone or an order number (at least one).\n\nRequired scope: `customers.read`. Risk level: `read`.","tags":["customers"],"security":[{"bearerAuth":["customers.read"]}],"parameters":[{"name":"storeId","in":"path","required":true,"description":"Store id from list_stores.","schema":{"type":"string","maxLength":80}},{"name":"email","in":"query","required":false,"description":"Customer email.","schema":{"type":"string","maxLength":160}},{"name":"phone","in":"query","required":false,"description":"Customer phone, any format.","schema":{"type":"string","maxLength":40}},{"name":"orderNumber","in":"query","required":false,"description":"An order number or id.","schema":{"type":"string","maxLength":60}},{"name":"limit","in":"query","required":false,"description":"How many orders (default 5).","schema":{"type":"integer","minimum":1,"maximum":20,"default":5}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"orders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Order id."},"number":{"type":"string","description":"Order number as shown to the customer (falls back to id)."},"status":{"type":"string","description":"Order status when known."},"total":{"type":"number","description":"Order total in `currency` when known."},"currency":{"type":"string","description":"Currency code when known."},"createdAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."},"items":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Product name."},"qty":{"type":"number","description":"Quantity when known."}},"additionalProperties":true,"required":["name"]},"description":"Up to 20 line items when the order carries them."},"itemCount":{"type":"number","description":"Number of items when known."},"coupons":{"type":"array","items":{},"description":"Up to 5 coupon codes applied, as stored on the order."},"shippingMethod":{"type":"string","description":"Shipping method when known."},"shippingCity":{"type":"string","description":"Shipping city when known."}},"additionalProperties":true,"required":["id","number","createdAt"]},"description":"Matching orders, newest first, up to `limit` (max 20)."},"storeId":{"type":"string","description":"The store searched."},"source":{"type":"string","description":"Backing store the orders were read from (e.g. redis)."}},"additionalProperties":true,"required":["ok","requestId","orders","storeId","source"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/stores/{storeId}/abandoned-carts":{"get":{"operationId":"list_abandoned_carts","summary":"Identified visitors who added to the cart in the last N hours and have not bought since: email and/or phone, when, the last product and the cart value","description":"Identified visitors who added to the cart in the last N hours and have not bought since: email and/or phone, when, the last product and the cart value. For cart-recovery messages — send only to people who already agreed to hear from the shop.\n\nRequired scope: `customers.read`. Risk level: `read`.","tags":["customers"],"security":[{"bearerAuth":["customers.read"]}],"parameters":[{"name":"storeId","in":"path","required":true,"description":"Store id from list_stores.","schema":{"type":"string","maxLength":80}},{"name":"hours","in":"query","required":false,"description":"How far back to look (1-72, default 24).","schema":{"type":"integer","minimum":1,"maximum":72,"default":24}},{"name":"minAgeMinutes","in":"query","required":false,"description":"Ignore carts younger than this — the visitor may still be checking out (15-720, default 60).","schema":{"type":"integer","minimum":15,"maximum":720,"default":60}},{"name":"limit","in":"query","required":false,"description":"How many carts (default 100).","schema":{"type":"integer","minimum":1,"maximum":500,"default":100}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"carts":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","description":"Email or \"\"."},"phone":{"type":"string","description":"Phone or \"\"."},"site":{"type":"string","description":"Site / publisher id the event came from."},"at":{"type":"string","description":"When the item was added, ISO 8601."},"product":{"type":"object","properties":{"id":{"type":"string","description":"Product id."},"name":{"type":"string","description":"Product name."},"price":{"type":"number","description":"Unit price, store currency."},"url":{"type":"string","description":"Product URL or \"\"."}},"additionalProperties":true,"required":["id","name","url"],"description":"Last product added (absent when the event carried none)."},"cartValue":{"type":"number","description":"Cart value at the time, store currency."}},"additionalProperties":true,"required":["email","phone","site","at"]},"description":"Identified visitors with an add-to-cart and no purchase since, newest first."},"hours":{"type":"integer","description":"Look-back window actually used (1-72)."}},"additionalProperties":true,"required":["ok","requestId","carts","hours"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/stores/{storeId}/orders/{orderId}/cancel":{"post":{"operationId":"cancel_order","summary":"Cancel one order in the connected store (WooCommerce, Shopify, Wix or the WordPress plugin)","description":"Cancel one order in the connected store (WooCommerce, Shopify, Wix or the WordPress plugin). Only orders not yet fulfilled can be cancelled; the store restocks the items and, where it can, emails the customer. Money is NOT returned by this tool — use refund_order for that.\n\nRequired scope: `orders.write`. Risk level: `write`.","tags":["orders"],"security":[{"bearerAuth":["orders.write"]}],"parameters":[{"name":"storeId","in":"path","required":true,"description":"Store id from list_stores.","schema":{"type":"string","maxLength":80}},{"name":"orderId","in":"path","required":true,"description":"The order number (as the customer sees it) or the store id of the order.","schema":{"type":"string","maxLength":80}},{"name":"reason","in":"query","required":false,"description":"Why, in a few words — kept on the order.","schema":{"type":"string","maxLength":200}},{"name":"notifyCustomer","in":"query","required":false,"description":"Let the store email the customer about the cancellation. Default true.","schema":{"type":"boolean","default":true}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"cancelled":{"type":"boolean","description":"Always true on success."},"platform":{"type":"string","description":"Store platform, e.g. woocommerce, shopify, wix."},"order":{"type":"object","properties":{"id":{"type":"string","description":"Platform order id."},"number":{"type":"string","description":"Order number as shown to the customer."},"status":{"type":"string","description":"Platform order status, e.g. processing, cancelled."},"financialStatus":{"type":"string","description":"Payment status (Shopify/Wix), e.g. paid, refunded."},"total":{"type":"number","description":"Order total in the store currency."},"currency":{"type":"string","description":"ISO 4217 currency code."},"refunded":{"type":"number","description":"Amount already refunded."},"createdAt":{"type":"string","description":"Order creation time (platform format)."},"customer":{"type":"object","properties":{"email":{"type":"string","description":"Email, lower-cased."},"phone":{"type":"string","description":"Phone."}},"additionalProperties":true,"required":["email","phone"],"description":"Customer contact."},"items":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Product name."},"qty":{"type":"integer","description":"Quantity."}},"additionalProperties":true,"required":["name","qty"]},"description":"Line items."},"shipping":{"type":"object","properties":{"name":{"type":"string","description":"Recipient name."},"address1":{"type":"string","description":"Address line 1."},"address2":{"type":"string","description":"Address line 2."},"city":{"type":"string","description":"City."},"state":{"type":"string","description":"State / province."},"postcode":{"type":"string","description":"Postal code."},"country":{"type":"string","description":"Country code or name."},"phone":{"type":"string","description":"Phone."}},"additionalProperties":true,"required":["name","address1","address2","city","state","postcode","country","phone"],"description":"Shipping address (absent when the order has none)."},"cancellable":{"type":"boolean","description":"true when the order can still be cancelled."},"pending":{"type":"boolean","description":"true when the platform queued the change asynchronously."}},"additionalProperties":true,"required":["id","number","status","refunded","customer","items","cancellable"],"description":"Normalised store order (WooCommerce / Shopify / Wix / plugin)."},"targetType":{"type":"string","enum":["order"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Order number."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","cancelled","platform","order","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/stores/{storeId}/orders/{orderId}/address":{"post":{"operationId":"update_order_address","summary":"Change the shipping address of one order in the connected store","description":"Change the shipping address of one order in the connected store. Give only the fields that change; the rest are kept. Refused by the store once the order has shipped.\n\nRequired scope: `orders.write`. Risk level: `write`.","tags":["orders"],"security":[{"bearerAuth":["orders.write"]}],"parameters":[{"name":"storeId","in":"path","required":true,"description":"Store id from list_stores.","schema":{"type":"string","maxLength":80}},{"name":"orderId","in":"path","required":true,"description":"The order number or the store id of the order.","schema":{"type":"string","maxLength":80}},{"name":"address","in":"query","required":true,"description":"Fields to change: name, address1, address2, city, state, postcode, country (ISO-2), phone.","schema":{"type":"string"}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"updated":{"type":"boolean","description":"Always true on success."},"platform":{"type":"string","description":"Store platform, e.g. woocommerce, shopify, wix."},"order":{"type":"object","properties":{"id":{"type":"string","description":"Platform order id."},"number":{"type":"string","description":"Order number as shown to the customer."},"status":{"type":"string","description":"Platform order status, e.g. processing, cancelled."},"financialStatus":{"type":"string","description":"Payment status (Shopify/Wix), e.g. paid, refunded."},"total":{"type":"number","description":"Order total in the store currency."},"currency":{"type":"string","description":"ISO 4217 currency code."},"refunded":{"type":"number","description":"Amount already refunded."},"createdAt":{"type":"string","description":"Order creation time (platform format)."},"customer":{"type":"object","properties":{"email":{"type":"string","description":"Email, lower-cased."},"phone":{"type":"string","description":"Phone."}},"additionalProperties":true,"required":["email","phone"],"description":"Customer contact."},"items":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Product name."},"qty":{"type":"integer","description":"Quantity."}},"additionalProperties":true,"required":["name","qty"]},"description":"Line items."},"shipping":{"type":"object","properties":{"name":{"type":"string","description":"Recipient name."},"address1":{"type":"string","description":"Address line 1."},"address2":{"type":"string","description":"Address line 2."},"city":{"type":"string","description":"City."},"state":{"type":"string","description":"State / province."},"postcode":{"type":"string","description":"Postal code."},"country":{"type":"string","description":"Country code or name."},"phone":{"type":"string","description":"Phone."}},"additionalProperties":true,"required":["name","address1","address2","city","state","postcode","country","phone"],"description":"Shipping address (absent when the order has none)."},"cancellable":{"type":"boolean","description":"true when the order can still be cancelled."},"pending":{"type":"boolean","description":"true when the platform queued the change asynchronously."}},"additionalProperties":true,"required":["id","number","status","refunded","customer","items","cancellable"],"description":"Normalised store order (WooCommerce / Shopify / Wix / plugin)."},"targetType":{"type":"string","enum":["order"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Order number."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","updated","platform","order","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/stores/{storeId}/orders/{orderId}/refund":{"post":{"operationId":"refund_order","summary":"Refund money on one order through the store's own payment gateway — the whole amount still refundable, or a partial amount","description":"Refund money on one order through the store's own payment gateway — the whole amount still refundable, or a partial amount. Two calls: a preview showing the order, what was paid and what would go back, then confirm:true with the token.\n\nRequired scope: `orders.write`. Risk level: `high`.","tags":["orders"],"security":[{"bearerAuth":["orders.write"]}],"parameters":[{"name":"storeId","in":"path","required":true,"description":"Store id from list_stores.","schema":{"type":"string","maxLength":80}},{"name":"orderId","in":"path","required":true,"description":"The order number or the store id of the order.","schema":{"type":"string","maxLength":80}},{"name":"amount","in":"query","required":false,"description":"Amount to refund in the order currency. Omit for everything still refundable.","schema":{"type":"number"}},{"name":"reason","in":"query","required":false,"description":"Why, in a few words — kept on the refund.","schema":{"type":"string","maxLength":200}},{"name":"notifyCustomer","in":"query","required":false,"description":"Let the store email the customer about the refund. Default true.","schema":{"type":"boolean","default":true}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"willRefund":{"type":"object","properties":{"amount":{"type":"number","description":"Amount to refund, 2 decimals, capped at the unrefunded balance."},"currency":{"type":"string","description":"ISO 4217 currency code."},"order":{"type":"object","properties":{"id":{"type":"string","description":"Platform order id."},"number":{"type":"string","description":"Order number as shown to the customer."},"status":{"type":"string","description":"Platform order status, e.g. processing, cancelled."},"financialStatus":{"type":"string","description":"Payment status (Shopify/Wix), e.g. paid, refunded."},"total":{"type":"number","description":"Order total in the store currency."},"currency":{"type":"string","description":"ISO 4217 currency code."},"refunded":{"type":"number","description":"Amount already refunded."},"createdAt":{"type":"string","description":"Order creation time (platform format)."},"customer":{"type":"object","properties":{"email":{"type":"string","description":"Email, lower-cased."},"phone":{"type":"string","description":"Phone."}},"additionalProperties":true,"required":["email","phone"],"description":"Customer contact."},"items":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Product name."},"qty":{"type":"integer","description":"Quantity."}},"additionalProperties":true,"required":["name","qty"]},"description":"Line items."},"shipping":{"type":"object","properties":{"name":{"type":"string","description":"Recipient name."},"address1":{"type":"string","description":"Address line 1."},"address2":{"type":"string","description":"Address line 2."},"city":{"type":"string","description":"City."},"state":{"type":"string","description":"State / province."},"postcode":{"type":"string","description":"Postal code."},"country":{"type":"string","description":"Country code or name."},"phone":{"type":"string","description":"Phone."}},"additionalProperties":true,"required":["name","address1","address2","city","state","postcode","country","phone"],"description":"Shipping address (absent when the order has none)."},"cancellable":{"type":"boolean","description":"true when the order can still be cancelled."},"pending":{"type":"boolean","description":"true when the platform queued the change asynchronously."}},"additionalProperties":true,"required":["id","number","status","refunded","customer","items","cancellable"],"description":"Normalised store order (WooCommerce / Shopify / Wix / plugin)."}},"additionalProperties":true,"required":["amount","order"],"description":"Preview only: what the refund would do."},"warning":{"type":"string","description":"Preview only: consequences of confirming."},"refunded":{"type":"boolean","description":"Run only: true on success."},"platform":{"type":"string","description":"Run only: store platform."},"refund":{"type":"object","properties":{"id":{"type":"string","description":"Platform refund id (\"\" if none)."},"amount":{"type":"number","description":"Refunded amount."},"currency":{"type":"string","description":"ISO 4217 currency code."},"external":{"description":"Wix only: set when the refund must be completed offline."}},"additionalProperties":true,"required":["id"],"description":"Run only: the refund the platform created."},"order":{"type":"object","properties":{"id":{"type":"string","description":"Platform order id."},"number":{"type":"string","description":"Order number as shown to the customer."},"status":{"type":"string","description":"Platform order status, e.g. processing, cancelled."},"financialStatus":{"type":"string","description":"Payment status (Shopify/Wix), e.g. paid, refunded."},"total":{"type":"number","description":"Order total in the store currency."},"currency":{"type":"string","description":"ISO 4217 currency code."},"refunded":{"type":"number","description":"Amount already refunded."},"createdAt":{"type":"string","description":"Order creation time (platform format)."},"customer":{"type":"object","properties":{"email":{"type":"string","description":"Email, lower-cased."},"phone":{"type":"string","description":"Phone."}},"additionalProperties":true,"required":["email","phone"],"description":"Customer contact."},"items":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Product name."},"qty":{"type":"integer","description":"Quantity."}},"additionalProperties":true,"required":["name","qty"]},"description":"Line items."},"shipping":{"type":"object","properties":{"name":{"type":"string","description":"Recipient name."},"address1":{"type":"string","description":"Address line 1."},"address2":{"type":"string","description":"Address line 2."},"city":{"type":"string","description":"City."},"state":{"type":"string","description":"State / province."},"postcode":{"type":"string","description":"Postal code."},"country":{"type":"string","description":"Country code or name."},"phone":{"type":"string","description":"Phone."}},"additionalProperties":true,"required":["name","address1","address2","city","state","postcode","country","phone"],"description":"Shipping address (absent when the order has none)."},"cancellable":{"type":"boolean","description":"true when the order can still be cancelled."},"pending":{"type":"boolean","description":"true when the platform queued the change asynchronously."}},"additionalProperties":true,"required":["id","number","status","refunded","customer","items","cancellable"],"description":"Run only: the order after the refund."},"targetType":{"type":"string","enum":["order"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Order number."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/stores/{storeId}/summary":{"get":{"operationId":"get_customer_summary","summary":"Store-level customer economics: customer count, orders, revenue, average order value, repeat-purchase rate and the ten highest-spending customers","description":"Store-level customer economics: customer count, orders, revenue, average order value, repeat-purchase rate and the ten highest-spending customers. Use it for \"how is this store doing?\" before drilling into individuals.\n\nRequired scope: `reports.read`. Risk level: `read`.","tags":["reports"],"security":[{"bearerAuth":["reports.read"]}],"parameters":[{"name":"storeId","in":"path","required":true,"description":"Store id from list_stores.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"storeId":{"type":"string","description":"The store summarized."},"source":{"type":"string","description":"Backing store the orders were read from (e.g. redis)."},"customers":{"type":"integer","description":"Distinct customers (within the 1000 most recent orders)."},"orders":{"type":"integer","description":"Total orders in the store."},"revenue":{"type":"number","description":"Sum of customer spend in `currency`, 2 decimals."},"currency":{"type":"string","description":"Currency code (\"\" when unknown)."},"avgOrderValue":{"type":"number","description":"revenue / orders, 2 decimals."},"repeatCustomers":{"type":"integer","description":"Customers with more than one order."},"repeatRate":{"type":"number","description":"repeatCustomers / customers in percent (0-100, 1 decimal)."},"topCustomers":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","description":"Lower-cased email (\"\" when none)."},"name":{"type":"string","description":"Name (\"\" when unknown)."},"orders":{"type":"integer","description":"Order count."},"totalSpend":{"type":"number","description":"Spend in `currency`."}},"additionalProperties":true,"required":["email","name","orders","totalSpend"]},"description":"Top 10 customers by spend."}},"additionalProperties":true,"required":["ok","requestId","storeId","source","customers","orders","revenue","currency","avgOrderValue","repeatCustomers","repeatRate","topCustomers"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/tasks":{"get":{"operationId":"list_tasks","summary":"CRM tasks in this workspace, soonest due first","description":"CRM tasks in this workspace, soonest due first. Open tasks only unless includeDone is true. Filter by owner, by due-date window, or by the record a task hangs off (relatedType contact/company/deal + relatedId).\n\nRequired scope: `tasks.read`. Risk level: `read`.","tags":["tasks"],"security":[{"bearerAuth":["tasks.read"]}],"parameters":[{"name":"query","in":"query","required":false,"description":"Substring of the task title.","schema":{"type":"string","maxLength":120}},{"name":"owner","in":"query","required":false,"description":"Assignee, exact match.","schema":{"type":"string","maxLength":120}},{"name":"includeDone","in":"query","required":false,"description":"Include completed tasks.","schema":{"type":"boolean","default":false}},{"name":"relatedType","in":"query","required":false,"description":"Only tasks attached to this record type.","schema":{"type":"string","enum":["contact","company","deal"]}},{"name":"relatedId","in":"query","required":false,"description":"Only tasks attached to this record id.","schema":{"type":"string","maxLength":80}},{"name":"dueFrom","in":"query","required":false,"description":"Only tasks due at or after this ISO 8601 date.","schema":{"type":"string","maxLength":40}},{"name":"dueTo","in":"query","required":false,"description":"Only tasks due at or before this ISO 8601 date.","schema":{"type":"string","maxLength":40}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"tasks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Task id."},"title":{"type":"string","description":"Task title (≤200 chars)."},"done":{"type":"boolean","description":"True when completed."},"priority":{"type":"string","description":"API priority: low | normal | high | urgent, or \"\" when none."},"priorityLabel":{"type":"string","description":"Priority label as stored on the board (e.g. Medium)."},"owner":{"type":"string","description":"Assignee (\"\" when unassigned)."},"dueAt":{"type":"string","description":"ISO 8601 due datetime (end of day when no time), \"\" when no due date."},"relatedTo":{"type":["object","null"],"properties":{"type":{"type":"string","description":"Entity type, e.g. contact, deal, company."},"id":{"type":"string","description":"Entity id."}},"additionalProperties":true,"required":["type","id"],"description":"Linked CRM entity, or null."},"createdAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."},"updatedAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."}},"additionalProperties":true,"required":["id","title","done","priority","priorityLabel","owner","dueAt","relatedTo","createdAt","updatedAt"]},"description":"Matching tasks, soonest due first (no due date last)."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (max 100)."},"total":{"type":"integer","description":"Total matching rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the (already filtered and sorted) result set."}},"additionalProperties":true,"required":["ok","requestId","tasks","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"create_task","summary":"Create a CRM task","description":"Create a CRM task. Attach it to a lead by passing relatedType \"contact\" and the lead id, and it will show on that lead and in list_leads_requiring_followup once overdue.\n\nRequired scope: `tasks.write`. Risk level: `write`.","tags":["tasks"],"security":[{"bearerAuth":["tasks.write"]}],"parameters":[{"name":"title","in":"query","required":true,"description":"What needs doing.","schema":{"type":"string","maxLength":200}},{"name":"dueDate","in":"query","required":false,"description":"ISO 8601 date, or date-time to set a time of day.","schema":{"type":"string","maxLength":40}},{"name":"owner","in":"query","required":false,"description":"Assign to this user (their email).","schema":{"type":"string","maxLength":120}},{"name":"priority","in":"query","required":false,"description":"Task priority.","schema":{"type":"string","enum":["low","normal","high","urgent"]}},{"name":"relatedType","in":"query","required":false,"description":"Attach the task to this record type.","schema":{"type":"string","enum":["contact","company","deal"]}},{"name":"relatedId","in":"query","required":false,"description":"Id of the record to attach to. Required with relatedType.","schema":{"type":"string","maxLength":80}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["task"],"description":"Always \"task\"."},"targetId":{"type":"string","description":"Id of the created task."},"created":{"type":"boolean","description":"Always true on success."},"task":{"type":"object","properties":{"id":{"type":"string","description":"Task id."},"title":{"type":"string","description":"Task title."},"done":{"type":"boolean","description":"True when the task is completed."},"priority":{"type":"string","description":"API priority: low | normal | high | urgent, or \"\" when unset."},"priorityLabel":{"type":"string","description":"Priority as stored on the board (e.g. Medium), \"\" when unset."},"owner":{"type":"string","description":"Assignee (email or name), \"\" when unassigned."},"dueAt":{"type":"string","description":"Due date/time as ISO 8601 (end of day when no time), \"\" when none."},"relatedTo":{"type":["object","null"],"properties":{"type":{"type":"string","description":"Entity type (e.g. contact, deal, company)."},"id":{"type":"string","description":"Entity id."}},"additionalProperties":true,"required":["type","id"],"description":"Linked CRM entity, null when the task is not linked."}},"additionalProperties":true,"required":["id","title","done","priority","priorityLabel","owner","dueAt","relatedTo"],"description":"The task as list_tasks would return it."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","created","task"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/tasks/{id}":{"get":{"operationId":"get_task","summary":"One CRM task by id: title, due date, assignee, priority, whether it is done, and the contact/company/deal it hangs off","description":"One CRM task by id: title, due date, assignee, priority, whether it is done, and the contact/company/deal it hangs off.\n\nRequired scope: `tasks.read`. Risk level: `read`.","tags":["tasks"],"security":[{"bearerAuth":["tasks.read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Task id from list_tasks.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"task":{"type":"object","properties":{"id":{"type":"string","description":"Task id."},"title":{"type":"string","description":"Task title (≤200 chars)."},"done":{"type":"boolean","description":"True when completed."},"priority":{"type":"string","description":"API priority: low | normal | high | urgent, or \"\" when none."},"priorityLabel":{"type":"string","description":"Priority label as stored on the board (e.g. Medium)."},"owner":{"type":"string","description":"Assignee (\"\" when unassigned)."},"dueAt":{"type":"string","description":"ISO 8601 due datetime (end of day when no time), \"\" when no due date."},"relatedTo":{"type":["object","null"],"properties":{"type":{"type":"string","description":"Entity type, e.g. contact, deal, company."},"id":{"type":"string","description":"Entity id."}},"additionalProperties":true,"required":["type","id"],"description":"Linked CRM entity, or null."},"createdAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."},"updatedAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."}},"additionalProperties":true,"required":["id","title","done","priority","priorityLabel","owner","dueAt","relatedTo","createdAt","updatedAt"],"description":"The task."}},"additionalProperties":true,"required":["ok","requestId","task"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/deals":{"get":{"operationId":"list_deals","summary":"Sales-pipeline deals in this workspace, soonest expected close first","description":"Sales-pipeline deals in this workspace, soonest expected close first. Open deals by default; each row carries stage, amount, currency, win probability, weighted amount, forecast category, owner, days in stage, linked contact/company ids and line items. The response also lists the pipeline stages this workspace uses.\n\nRequired scope: `deals.read`. Risk level: `read`.","tags":["deals"],"security":[{"bearerAuth":["deals.read"]}],"parameters":[{"name":"status","in":"query","required":false,"description":"Which deals: 'open' (default), 'won', 'lost' or 'all'.","schema":{"type":"string","enum":["open","won","lost","all"]}},{"name":"stage","in":"query","required":false,"description":"Only deals in this pipeline stage (exact name, see the stages list in any list_deals response).","schema":{"type":"string","maxLength":40}},{"name":"pipeline","in":"query","required":false,"description":"Only deals in this pipeline (id or name; the response lists the pipelines this workspace has).","schema":{"type":"string","maxLength":60}},{"name":"owner","in":"query","required":false,"description":"Only deals owned by this person (exact owner text).","schema":{"type":"string","maxLength":120}},{"name":"query","in":"query","required":false,"description":"Substring of the deal name, company name or next step.","schema":{"type":"string","maxLength":120}},{"name":"contactId","in":"query","required":false,"description":"Only deals linked to this contact / lead id.","schema":{"type":"string","maxLength":80}},{"name":"companyId","in":"query","required":false,"description":"Only deals linked to this company id.","schema":{"type":"string","maxLength":80}},{"name":"minAmount","in":"query","required":false,"description":"Only deals with at least this amount.","schema":{"type":"number"}},{"name":"closeFrom","in":"query","required":false,"description":"Only deals whose expected close date is on/after this date (YYYY-MM-DD).","schema":{"type":"string","maxLength":10}},{"name":"closeTo","in":"query","required":false,"description":"Only deals whose expected close date is on/before this date (YYYY-MM-DD).","schema":{"type":"string","maxLength":10}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"deals":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Deal id."},"name":{"type":"string","description":"Deal name."},"stage":{"type":"string","description":"Current stage name; \"Closed Won\" / \"Closed Lost\" when closed."},"pipeline":{"type":"string","description":"Pipeline id (\"default\" for the main pipeline)."},"pipelineName":{"type":"string","description":"Pipeline display name."},"open":{"type":"boolean","description":"True unless the stage starts with \"Closed\"."},"amount":{"type":"number","description":"Deal value in `currency` (0 when unset)."},"currency":{"type":"string","description":"ISO 4217 code; falls back to the workspace CRM currency."},"probability":{"type":"number","description":"Win probability 0-100 (deal-specific, else stage default)."},"weightedAmount":{"type":"number","description":"amount × probability / 100."},"forecastCategory":{"type":"string","description":"Commit | Best case | Pipeline | Omit (or custom); \"\" for closed deals."},"closeDate":{"type":"string","description":"Expected close date YYYY-MM-DD (\"\" when unset)."},"closedAt":{"type":"string","description":"ISO 8601 actual close time (\"\" when open)."},"owner":{"type":"string","description":"Owner email/name (\"\" when unassigned)."},"dealType":{"type":"string","description":"Free-form deal type (\"\" when unset)."},"priority":{"type":"string","description":"Free-form priority (\"\" when unset)."},"nextStep":{"type":"string","description":"Next step text (≤300 chars)."},"lostReason":{"type":"string","description":"Lost reason (\"\" unless lost)."},"daysInStage":{"type":"integer","description":"Whole days since the deal entered its current stage (0 when closed)."},"stageEnteredAt":{"type":"string","description":"ISO 8601 time the current stage was entered (\"\" when unknown)."},"stageHistory":{"type":"array","items":{"type":"object","properties":{"from":{"type":"string","description":"Previous stage."},"to":{"type":"string","description":"New stage."},"at":{"type":"string","description":"ISO 8601."},"by":{"type":"string","description":"Who moved it."}},"additionalProperties":true,"required":["from","to","at","by"]},"description":"Last 20 stage transitions, oldest first."},"contactIds":{"type":"array","items":{"type":"string"},"description":"Linked contact (lead) ids."},"companyIds":{"type":"array","items":{"type":"string"},"description":"Linked company ids."},"companies":{"type":"array","items":{"type":"string"},"description":"Names of the linked companies that resolved."},"lineItems":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Item name."},"sku":{"type":"string","description":"SKU (\"\" when none)."},"quantity":{"type":"number","description":"Quantity (0 when unset)."},"unitPrice":{"type":"number","description":"Unit price in the deal currency."}},"additionalProperties":true,"required":["name","sku","quantity","unitPrice"]},"description":"Up to 50 line items."},"description":{"type":"string","description":"Description (≤2000 chars)."},"createdAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."},"updatedAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."}},"additionalProperties":true,"required":["id","name","stage","pipeline","pipelineName","open","amount","currency","probability","weightedAmount","forecastCategory","closeDate","closedAt","owner","dealType","priority","nextStep","lostReason","daysInStage","stageEnteredAt","stageHistory","contactIds","companyIds","companies","lineItems","description","createdAt","updatedAt"]},"description":"Matching deals, earliest close date first."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (max 100)."},"total":{"type":"integer","description":"Total matching rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the (already filtered and sorted) result set."},"stages":{"type":"array","items":{"type":"string"},"description":"Default pipeline stage names, open stages then Closed Won / Closed Lost."},"currency":{"type":"string","description":"Workspace CRM currency (ISO 4217, default USD)."},"pipelines":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Pipeline id (\"default\" for the main one)."},"name":{"type":"string","description":"Pipeline name."},"stages":{"type":"array","items":{"type":"string"},"description":"Stage names, open stages then Closed Won / Closed Lost."}},"additionalProperties":true,"required":["id","name","stages"]},"description":"All pipelines and their stage lists."}},"additionalProperties":true,"required":["ok","requestId","deals","pagination","stages","currency","pipelines"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"create_deal","summary":"Create a sales deal in the pipeline, optionally linked to contacts and companies","description":"Create a sales deal in the pipeline, optionally linked to contacts and companies. Defaults to the first open stage; stage names must match this workspace's pipeline (see list_deals). Stage history starts with the creation.\n\nRequired scope: `deals.write`. Risk level: `write`.","tags":["deals"],"security":[{"bearerAuth":["deals.write"]}],"parameters":[{"name":"name","in":"query","required":true,"description":"Deal name.","schema":{"type":"string","maxLength":200}},{"name":"amount","in":"query","required":false,"description":"Deal amount in the deal currency.","schema":{"type":"number"}},{"name":"currency","in":"query","required":false,"description":"3-letter ISO currency; defaults to the workspace pipeline currency.","schema":{"type":"string","maxLength":3}},{"name":"pipeline","in":"query","required":false,"description":"Pipeline id or name; defaults to the workspace default pipeline.","schema":{"type":"string","maxLength":60}},{"name":"stage","in":"query","required":false,"description":"Pipeline stage name (of that pipeline); defaults to its first open stage.","schema":{"type":"string","maxLength":40}},{"name":"closeDate","in":"query","required":false,"description":"Expected close date, YYYY-MM-DD.","schema":{"type":"string","maxLength":10}},{"name":"owner","in":"query","required":false,"description":"Owner name or email.","schema":{"type":"string","maxLength":120}},{"name":"probability","in":"query","required":false,"description":"Win probability 0-100; omit to use the stage default.","schema":{"type":"number"}},{"name":"forecastCategory","in":"query","required":false,"description":"Forecast category override.","schema":{"type":"string","enum":["Pipeline","Best case","Commit","Omit"]}},{"name":"dealType","in":"query","required":false,"description":"e.g. New business, Existing business, Renewal, Upsell.","schema":{"type":"string","maxLength":40}},{"name":"priority","in":"query","required":false,"description":"Low, Medium or High.","schema":{"type":"string","enum":["Low","Medium","High"]}},{"name":"nextStep","in":"query","required":false,"description":"What happens next on this deal.","schema":{"type":"string","maxLength":300}},{"name":"description","in":"query","required":false,"description":"Free-text description.","schema":{"type":"string","maxLength":2000}},{"name":"contactIds","in":"query","required":false,"description":"Contact / lead ids to link to the deal.","schema":{"type":"array","items":{"type":"string"}}},{"name":"companyIds","in":"query","required":false,"description":"Company ids to link to the deal.","schema":{"type":"array","items":{"type":"string"}}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["deal"],"description":"Always \"deal\"."},"targetId":{"type":"string","description":"Id of the created deal."},"created":{"type":"boolean","description":"Always true on success."},"deal":{"type":"object","properties":{"id":{"type":"string","description":"Deal id."},"name":{"type":"string","description":"Deal name."},"stage":{"type":"string","description":"Current pipeline stage name."},"pipeline":{"type":"string","description":"Pipeline id (\"default\" for the main pipeline)."},"pipelineName":{"type":"string","description":"Pipeline display name."},"open":{"type":"boolean","description":"False once the stage starts with \"Closed\"."},"amount":{"type":"number","description":"Deal value in `currency`; 0 when unset."},"currency":{"type":"string","description":"3-letter ISO currency code (workspace default when unset)."},"probability":{"type":"number","description":"Win probability 0-100 (own value or derived from the stage)."},"weightedAmount":{"type":"number","description":"amount × probability / 100."},"forecastCategory":{"type":"string","description":"Pipeline | Best case | Commit | Omit (derived when unset); \"\" for closed deals."},"closeDate":{"type":"string","description":"Expected close date YYYY-MM-DD, \"\" when unset."},"closedAt":{"type":"string","description":"ISO 8601 time the deal was closed, \"\" when open."},"owner":{"type":"string","description":"Deal owner, \"\" when unassigned."},"dealType":{"type":"string","description":"Free-text deal type, \"\" when unset."},"priority":{"type":"string","description":"Free-text priority, \"\" when unset."},"nextStep":{"type":"string","description":"Next step text, \"\" when unset."},"lostReason":{"type":"string","description":"Reason when Closed Lost, \"\" otherwise."},"daysInStage":{"type":"integer","description":"Whole days since entering the current stage; 0 for closed deals."},"stageEnteredAt":{"type":"string","description":"ISO 8601 time the current stage was entered, \"\" when unknown."},"stageHistory":{"type":"array","items":{"type":"object","properties":{"from":{"type":"string","description":"Previous stage, \"\" for the first entry."},"to":{"type":"string","description":"New stage."},"at":{"type":"string","description":"ISO 8601 time of the transition, \"\" when unknown."},"by":{"type":"string","description":"Who moved it, \"\" when unknown."}},"additionalProperties":true,"required":["from","to","at","by"],"description":"One stage transition."},"description":"Last 20 stage transitions, oldest first."},"contactIds":{"type":"array","items":{"type":"string","description":"Contact id."},"description":"Linked contact (lead) ids."},"companyIds":{"type":"array","items":{"type":"string","description":"Company id."},"description":"Linked company ids."},"companies":{"type":"array","items":{"type":"string","description":"Company name."},"description":"Names of the linked companies that resolved."},"lineItems":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Item name."},"sku":{"type":"string","description":"SKU, \"\" when none."},"quantity":{"type":"number","description":"Quantity; 0 when unset."},"unitPrice":{"type":"number","description":"Unit price in the deal currency; 0 when unset."}},"additionalProperties":true,"required":["name","sku","quantity","unitPrice"],"description":"One product line item."},"description":"Up to 50 product line items."},"description":{"type":"string","description":"Description, \"\" when none."},"createdAt":{"type":"string","description":"ISO 8601 creation time, \"\" when unknown."},"updatedAt":{"type":"string","description":"ISO 8601 last update time, \"\" when unknown."}},"additionalProperties":true,"required":["id","name","stage","pipeline","pipelineName","open","amount","currency","probability","weightedAmount","forecastCategory","closeDate","closedAt","owner","dealType","priority","nextStep","lostReason","daysInStage","stageEnteredAt","stageHistory","contactIds","companyIds","companies","lineItems","description","createdAt","updatedAt"],"description":"The deal as get_deal would return it, rebuilt from the saved record."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","created","deal"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/deals/{id}":{"get":{"operationId":"get_deal","summary":"One deal by id with its full stage history (who moved it, when), line items, linked contacts and companies, lost reason and closed date","description":"One deal by id with its full stage history (who moved it, when), line items, linked contacts and companies, lost reason and closed date.\n\nRequired scope: `deals.read`. Risk level: `read`.","tags":["deals"],"security":[{"bearerAuth":["deals.read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Deal id from list_deals.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"deal":{"type":"object","properties":{"id":{"type":"string","description":"Deal id."},"name":{"type":"string","description":"Deal name."},"stage":{"type":"string","description":"Current stage name; \"Closed Won\" / \"Closed Lost\" when closed."},"pipeline":{"type":"string","description":"Pipeline id (\"default\" for the main pipeline)."},"pipelineName":{"type":"string","description":"Pipeline display name."},"open":{"type":"boolean","description":"True unless the stage starts with \"Closed\"."},"amount":{"type":"number","description":"Deal value in `currency` (0 when unset)."},"currency":{"type":"string","description":"ISO 4217 code; falls back to the workspace CRM currency."},"probability":{"type":"number","description":"Win probability 0-100 (deal-specific, else stage default)."},"weightedAmount":{"type":"number","description":"amount × probability / 100."},"forecastCategory":{"type":"string","description":"Commit | Best case | Pipeline | Omit (or custom); \"\" for closed deals."},"closeDate":{"type":"string","description":"Expected close date YYYY-MM-DD (\"\" when unset)."},"closedAt":{"type":"string","description":"ISO 8601 actual close time (\"\" when open)."},"owner":{"type":"string","description":"Owner email/name (\"\" when unassigned)."},"dealType":{"type":"string","description":"Free-form deal type (\"\" when unset)."},"priority":{"type":"string","description":"Free-form priority (\"\" when unset)."},"nextStep":{"type":"string","description":"Next step text (≤300 chars)."},"lostReason":{"type":"string","description":"Lost reason (\"\" unless lost)."},"daysInStage":{"type":"integer","description":"Whole days since the deal entered its current stage (0 when closed)."},"stageEnteredAt":{"type":"string","description":"ISO 8601 time the current stage was entered (\"\" when unknown)."},"stageHistory":{"type":"array","items":{"type":"object","properties":{"from":{"type":"string","description":"Previous stage."},"to":{"type":"string","description":"New stage."},"at":{"type":"string","description":"ISO 8601."},"by":{"type":"string","description":"Who moved it."}},"additionalProperties":true,"required":["from","to","at","by"]},"description":"Last 20 stage transitions, oldest first."},"contactIds":{"type":"array","items":{"type":"string"},"description":"Linked contact (lead) ids."},"companyIds":{"type":"array","items":{"type":"string"},"description":"Linked company ids."},"companies":{"type":"array","items":{"type":"string"},"description":"Names of the linked companies that resolved."},"lineItems":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Item name."},"sku":{"type":"string","description":"SKU (\"\" when none)."},"quantity":{"type":"number","description":"Quantity (0 when unset)."},"unitPrice":{"type":"number","description":"Unit price in the deal currency."}},"additionalProperties":true,"required":["name","sku","quantity","unitPrice"]},"description":"Up to 50 line items."},"description":{"type":"string","description":"Description (≤2000 chars)."},"createdAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."},"updatedAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."}},"additionalProperties":true,"required":["id","name","stage","pipeline","pipelineName","open","amount","currency","probability","weightedAmount","forecastCategory","closeDate","closedAt","owner","dealType","priority","nextStep","lostReason","daysInStage","stageEnteredAt","stageHistory","contactIds","companyIds","companies","lineItems","description","createdAt","updatedAt"],"description":"The deal."}},"additionalProperties":true,"required":["ok","requestId","deal"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"patch":{"operationId":"update_deal","summary":"Update a deal: move it to another stage (including Closed Won / Closed Lost with a lost reason), change amount, close date, owner, probability, forecast category, next step, or link more contacts and companies","description":"Update a deal: move it to another stage (including Closed Won / Closed Lost with a lost reason), change amount, close date, owner, probability, forecast category, next step, or link more contacts and companies. Stage moves are recorded in the deal's stage history.\n\nRequired scope: `deals.write`. Risk level: `write`.","tags":["deals"],"security":[{"bearerAuth":["deals.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Deal id from list_deals.","schema":{"type":"string","maxLength":80}},{"name":"name","in":"query","required":false,"description":"New deal name.","schema":{"type":"string","maxLength":200}},{"name":"pipeline","in":"query","required":false,"description":"Move the deal to another pipeline (id or name); its stage is kept when that pipeline has it, else reset to the first stage.","schema":{"type":"string","maxLength":60}},{"name":"stage","in":"query","required":false,"description":"Pipeline stage to move the deal to (exact name; Closed Won / Closed Lost close it).","schema":{"type":"string","maxLength":40}},{"name":"lostReason","in":"query","required":false,"description":"Why the deal was lost (used with stage Closed Lost).","schema":{"type":"string","maxLength":120}},{"name":"amount","in":"query","required":false,"description":"Deal amount in the deal currency.","schema":{"type":"number"}},{"name":"currency","in":"query","required":false,"description":"3-letter ISO currency.","schema":{"type":"string","maxLength":3}},{"name":"closeDate","in":"query","required":false,"description":"Expected close date, YYYY-MM-DD.","schema":{"type":"string","maxLength":10}},{"name":"owner","in":"query","required":false,"description":"Owner name or email.","schema":{"type":"string","maxLength":120}},{"name":"probability","in":"query","required":false,"description":"Win probability 0-100.","schema":{"type":"number"}},{"name":"forecastCategory","in":"query","required":false,"description":"Forecast category override.","schema":{"type":"string","enum":["Pipeline","Best case","Commit","Omit"]}},{"name":"dealType","in":"query","required":false,"description":"e.g. New business, Existing business, Renewal, Upsell.","schema":{"type":"string","maxLength":40}},{"name":"priority","in":"query","required":false,"description":"Low, Medium or High.","schema":{"type":"string","enum":["Low","Medium","High"]}},{"name":"nextStep","in":"query","required":false,"description":"What happens next on this deal.","schema":{"type":"string","maxLength":300}},{"name":"description","in":"query","required":false,"description":"Free-text description.","schema":{"type":"string","maxLength":2000}},{"name":"contactIds","in":"query","required":false,"description":"Additional contact / lead ids to link.","schema":{"type":"array","items":{"type":"string"}}},{"name":"companyIds","in":"query","required":false,"description":"Additional company ids to link.","schema":{"type":"array","items":{"type":"string"}}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["deal"],"description":"Always \"deal\"."},"targetId":{"type":"string","description":"Id of the updated deal."},"updated":{"type":"boolean","description":"Always true on success."},"deal":{"type":"object","properties":{"id":{"type":"string","description":"Deal id."},"name":{"type":"string","description":"Deal name."},"stage":{"type":"string","description":"Current pipeline stage name."},"pipeline":{"type":"string","description":"Pipeline id (\"default\" for the main pipeline)."},"pipelineName":{"type":"string","description":"Pipeline display name."},"open":{"type":"boolean","description":"False once the stage starts with \"Closed\"."},"amount":{"type":"number","description":"Deal value in `currency`; 0 when unset."},"currency":{"type":"string","description":"3-letter ISO currency code (workspace default when unset)."},"probability":{"type":"number","description":"Win probability 0-100 (own value or derived from the stage)."},"weightedAmount":{"type":"number","description":"amount × probability / 100."},"forecastCategory":{"type":"string","description":"Pipeline | Best case | Commit | Omit (derived when unset); \"\" for closed deals."},"closeDate":{"type":"string","description":"Expected close date YYYY-MM-DD, \"\" when unset."},"closedAt":{"type":"string","description":"ISO 8601 time the deal was closed, \"\" when open."},"owner":{"type":"string","description":"Deal owner, \"\" when unassigned."},"dealType":{"type":"string","description":"Free-text deal type, \"\" when unset."},"priority":{"type":"string","description":"Free-text priority, \"\" when unset."},"nextStep":{"type":"string","description":"Next step text, \"\" when unset."},"lostReason":{"type":"string","description":"Reason when Closed Lost, \"\" otherwise."},"daysInStage":{"type":"integer","description":"Whole days since entering the current stage; 0 for closed deals."},"stageEnteredAt":{"type":"string","description":"ISO 8601 time the current stage was entered, \"\" when unknown."},"stageHistory":{"type":"array","items":{"type":"object","properties":{"from":{"type":"string","description":"Previous stage, \"\" for the first entry."},"to":{"type":"string","description":"New stage."},"at":{"type":"string","description":"ISO 8601 time of the transition, \"\" when unknown."},"by":{"type":"string","description":"Who moved it, \"\" when unknown."}},"additionalProperties":true,"required":["from","to","at","by"],"description":"One stage transition."},"description":"Last 20 stage transitions, oldest first."},"contactIds":{"type":"array","items":{"type":"string","description":"Contact id."},"description":"Linked contact (lead) ids."},"companyIds":{"type":"array","items":{"type":"string","description":"Company id."},"description":"Linked company ids."},"companies":{"type":"array","items":{"type":"string","description":"Company name."},"description":"Names of the linked companies that resolved."},"lineItems":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Item name."},"sku":{"type":"string","description":"SKU, \"\" when none."},"quantity":{"type":"number","description":"Quantity; 0 when unset."},"unitPrice":{"type":"number","description":"Unit price in the deal currency; 0 when unset."}},"additionalProperties":true,"required":["name","sku","quantity","unitPrice"],"description":"One product line item."},"description":"Up to 50 product line items."},"description":{"type":"string","description":"Description, \"\" when none."},"createdAt":{"type":"string","description":"ISO 8601 creation time, \"\" when unknown."},"updatedAt":{"type":"string","description":"ISO 8601 last update time, \"\" when unknown."}},"additionalProperties":true,"required":["id","name","stage","pipeline","pipelineName","open","amount","currency","probability","weightedAmount","forecastCategory","closeDate","closedAt","owner","dealType","priority","nextStep","lostReason","daysInStage","stageEnteredAt","stageHistory","contactIds","companyIds","companies","lineItems","description","createdAt","updatedAt"],"description":"The deal as get_deal would return it, rebuilt from the saved record."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","updated","deal"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/deals/forecast":{"get":{"operationId":"get_pipeline_forecast","summary":"Pipeline forecast for this workspace: open amount and weighted amount, totals by stage, by forecast category (Commit / Best case / Pipeline), by expected close month and by owner, won this month and quarter versus the configured targets, win rate, average deal size and sales cycle, plus hygiene counts (stale, past close date, no close date)","description":"Pipeline forecast for this workspace: open amount and weighted amount, totals by stage, by forecast category (Commit / Best case / Pipeline), by expected close month and by owner, won this month and quarter versus the configured targets, win rate, average deal size and sales cycle, plus hygiene counts (stale, past close date, no close date).\n\nRequired scope: `deals.read`. Risk level: `read`.","tags":["deals"],"security":[{"bearerAuth":["deals.read"]}],"parameters":[{"name":"months","in":"query","required":false,"description":"How many close months ahead to break down (1-12, default 6).","schema":{"type":"integer"}},{"name":"pipeline","in":"query","required":false,"description":"Restrict the forecast to one pipeline (id or name); omit for every pipeline together.","schema":{"type":"string","maxLength":60}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"currency":{"type":"string","description":"Workspace CRM currency for every amount below."},"asOf":{"type":"string","description":"Report date YYYY-MM-DD (UTC)."},"pipeline":{"type":["object","null"],"properties":{"id":{"type":"string","description":"Pipeline id."},"name":{"type":"string","description":"Pipeline name."}},"additionalProperties":true,"required":["id","name"],"description":"The pipeline the forecast is limited to; null = all pipelines."},"pipelines":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Pipeline id."},"name":{"type":"string","description":"Pipeline name."},"openCount":{"type":"integer","description":"Open deals in this pipeline."}},"additionalProperties":true,"required":["id","name","openCount"]},"description":"Every pipeline with its open-deal count."},"open":{"type":"object","properties":{"count":{"type":"integer","description":"Open deals."},"amount":{"type":"number","description":"Sum of open deal amounts."},"weightedAmount":{"type":"number","description":"Sum of open weighted amounts (amount × probability)."}},"additionalProperties":true,"required":["count","amount","weightedAmount"],"description":"All open deals."},"byForecastCategory":{"type":"array","items":{"type":"object","properties":{"category":{"type":"string","enum":["Commit","Best case","Pipeline","Omit"],"description":"Forecast category."},"count":{"type":"integer","description":"Open deals in the category."},"amount":{"type":"number","description":"Sum of their amounts."}},"additionalProperties":true,"required":["category","count","amount"]},"description":"Open deals split by forecast category."},"wonThisMonth":{"type":"object","properties":{"count":{"type":"integer","description":"Deals won."},"amount":{"type":"number","description":"Sum won."}},"additionalProperties":true,"required":["count","amount"],"description":"Deals closed won this calendar month."},"wonThisQuarter":{"type":"object","properties":{"quarter":{"type":"string","description":"Quarter label, e.g. 2026-Q3."},"count":{"type":"integer","description":"Deals won."},"amount":{"type":"number","description":"Sum won."}},"additionalProperties":true,"required":["quarter","count","amount"],"description":"Deals closed won this calendar quarter."},"target":{"type":"object","properties":{"monthly":{"type":"number","description":"Monthly target."},"quarterly":{"type":"number","description":"Quarterly target."}},"additionalProperties":true,"required":["monthly","quarterly"],"description":"Revenue targets configured in CRM settings (0 when unset)."},"winRate":{"type":["integer","null"],"description":"Won / closed in percent (0-100); null when nothing has closed."},"winRateBasis":{"type":"string","enum":["last 90 days","all time"],"description":"Window the win rate was computed over."},"avgDealSize":{"type":["number","null"],"description":"Average won amount (rounded); null when nothing was won."},"avgSalesCycleDays":{"type":["integer","null"],"description":"Average days from creation to close for won deals; null when unknown."},"staleDeals":{"type":"integer","description":"Open deals sitting in their stage for at least staleAfterDays."},"staleAfterDays":{"type":"integer","description":"Stale threshold in days (CRM setting, default 14)."},"overdueDeals":{"type":"integer","description":"Open deals whose close date is in the past."},"noCloseDate":{"type":"integer","description":"Open deals without a close date."},"byStage":{"type":"array","items":{"type":"object","properties":{"stage":{"type":"string","description":"Stage name."},"probability":{"type":"number","description":"Default win probability for the stage (0-100)."},"count":{"type":"integer","description":"Deals in the stage."},"amount":{"type":"number","description":"Sum of amounts."},"weightedAmount":{"type":"number","description":"Sum of weighted amounts."}},"additionalProperties":true,"required":["stage","probability","count","amount","weightedAmount"]},"description":"Every stage (open and closed) with totals."},"byCloseMonth":{"type":"array","items":{"type":"object","properties":{"month":{"type":"string","description":"Month YYYY-MM."},"openCount":{"type":"integer","description":"Open deals expected to close that month."},"openAmount":{"type":"number","description":"Their amount."},"weightedAmount":{"type":"number","description":"Their weighted amount."},"wonCount":{"type":"integer","description":"Deals already won with a close date in that month."},"wonAmount":{"type":"number","description":"Their amount."}},"additionalProperties":true,"required":["month","openCount","openAmount","weightedAmount","wonCount","wonAmount"]},"description":"One row per month from this month forward (`months`, default 6)."},"byOwner":{"type":"array","items":{"type":"object","properties":{"owner":{"type":"string","description":"Owner, or \"(unassigned)\"."},"openCount":{"type":"integer","description":"Open deals."},"openAmount":{"type":"number","description":"Open amount."},"weightedAmount":{"type":"number","description":"Open weighted amount."},"wonCount":{"type":"integer","description":"Deals won (all time)."},"wonAmount":{"type":"number","description":"Amount won (all time)."},"wonThisMonth":{"type":"number","description":"Amount won this calendar month."},"monthlyTarget":{"type":["number","null"],"description":"Owner monthly target; null when none set."},"targetProgress":{"type":["integer","null"],"description":"wonThisMonth / monthlyTarget in percent; null without a target."},"winRate":{"type":["integer","null"],"description":"Won / closed in percent; null when nothing closed."}},"additionalProperties":true,"required":["owner","openCount","openAmount","weightedAmount","wonCount","wonAmount","wonThisMonth","monthlyTarget","targetProgress","winRate"]},"description":"Per-owner pipeline and attainment, sorted by owner."}},"additionalProperties":true,"required":["ok","requestId","currency","asOf","pipeline","pipelines","open","byForecastCategory","wonThisMonth","wonThisQuarter","target","winRate","winRateBasis","avgDealSize","avgSalesCycleDays","staleDeals","staleAfterDays","overdueDeals","noCloseDate","byStage","byCloseMonth","byOwner"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/tasks/overdue":{"get":{"operationId":"list_overdue_tasks","summary":"Open tasks past their due date, most overdue first, each with how many days late it is","description":"Open tasks past their due date, most overdue first, each with how many days late it is. Optionally scoped to one owner.\n\nRequired scope: `tasks.read`. Risk level: `read`.","tags":["tasks"],"security":[{"bearerAuth":["tasks.read"]}],"parameters":[{"name":"owner","in":"query","required":false,"description":"Assignee, exact match.","schema":{"type":"string","maxLength":120}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"tasks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Task id."},"title":{"type":"string","description":"Task title (≤200 chars)."},"done":{"type":"boolean","description":"True when completed."},"priority":{"type":"string","description":"API priority: low | normal | high | urgent, or \"\" when none."},"priorityLabel":{"type":"string","description":"Priority label as stored on the board (e.g. Medium)."},"owner":{"type":"string","description":"Assignee (\"\" when unassigned)."},"dueAt":{"type":"string","description":"ISO 8601 due datetime (end of day when no time), \"\" when no due date."},"relatedTo":{"type":["object","null"],"properties":{"type":{"type":"string","description":"Entity type, e.g. contact, deal, company."},"id":{"type":"string","description":"Entity id."}},"additionalProperties":true,"required":["type","id"],"description":"Linked CRM entity, or null."},"createdAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."},"updatedAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."},"overdueDays":{"type":"integer","description":"Whole days past due."}},"additionalProperties":true,"required":["id","title","done","priority","priorityLabel","owner","dueAt","relatedTo","createdAt","updatedAt","overdueDays"]},"description":"Open tasks past their due time, most overdue first."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (max 100)."},"total":{"type":"integer","description":"Total matching rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the (already filtered and sorted) result set."}},"additionalProperties":true,"required":["ok","requestId","tasks","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/ad-accounts":{"get":{"operationId":"list_ad_accounts","summary":"Ad accounts this token may see, across Meta, Google Ads and DV360, with currency","description":"Ad accounts this token may see, across Meta, Google Ads and DV360, with currency. Campaign ids are only unique within a platform, so start here and pass accountId + platform downstream.\n\nRequired scope: `campaigns.read`. Risk level: `read`.","tags":["campaigns"],"security":[{"bearerAuth":["campaigns.read"]}],"parameters":[{"name":"platform","in":"query","required":false,"description":"Restrict to one platform.","schema":{"type":"string","enum":["meta","google","dv360"]}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"adAccounts":{"type":"array","items":{"type":"object","properties":{"platform":{"type":"string","enum":["meta","google","dv360"],"description":"Ad platform."},"id":{"type":"string","description":"Account id without act_ prefix or dashes; pass as accountId to list_campaigns."},"name":{"type":"string","description":"Account name."},"currency":{"type":"string","description":"Account currency code (\"\" when unknown)."},"status":{"type":"string","description":"Meta only: ACTIVE, INACTIVE or \"\"."},"managerId":{"type":"string","description":"Google only: manager (MCC) customer id, \"\" when none."}},"additionalProperties":true,"required":["platform","id","name","currency"]},"description":"Ad accounts across Meta, Google Ads and DV360 that this token may read."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (max 100)."},"total":{"type":"integer","description":"Total matching rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the (already filtered and sorted) result set."}},"additionalProperties":true,"required":["ok","requestId","adAccounts","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/campaigns":{"get":{"operationId":"list_campaigns","summary":"Ad campaigns with their performance for a date preset (default last_30d): spend, impressions, clicks, results, CTR, CPC and cost per result, highest spend first","description":"Ad campaigns with their performance for a date preset (default last_30d): spend, impressions, clicks, results, CTR, CPC and cost per result, highest spend first. Reads the platform's synced cache, so figures are as fresh as the last sync, not live. Without accountId it reads the first few accounts and says so in `notes` — pass accountId for a complete, cheap answer.\n\nRequired scope: `campaigns.read`. Risk level: `read`.","tags":["campaigns"],"security":[{"bearerAuth":["campaigns.read"]}],"parameters":[{"name":"platform","in":"query","required":false,"description":"Restrict to one platform.","schema":{"type":"string","enum":["meta","google","dv360"]}},{"name":"accountId","in":"query","required":false,"description":"Ad account id from list_ad_accounts.","schema":{"type":"string","maxLength":60}},{"name":"status","in":"query","required":false,"description":"Campaign status, e.g. ACTIVE or PAUSED.","schema":{"type":"string","maxLength":30}},{"name":"query","in":"query","required":false,"description":"Substring of the campaign name, or an exact campaign id.","schema":{"type":"string","maxLength":120}},{"name":"datePreset","in":"query","required":false,"description":"Reporting window.","schema":{"type":"string","enum":["today","yesterday","last_7d","last_14d","last_30d","this_month","last_month","maximum"],"default":"last_30d"}},{"name":"sort","in":"query","required":false,"description":"Result order.","schema":{"type":"string","enum":["spend_desc","name_asc"],"default":"spend_desc"}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"campaigns":{"type":"array","items":{"type":"object","properties":{"platform":{"type":"string","enum":["meta","google","dv360"],"description":"Ad platform."},"accountId":{"type":"string","description":"Ad account id without the act_ prefix (\"\" when unknown)."},"id":{"type":"string","description":"Campaign id, platform-specific (Google gads_ prefix stripped)."},"name":{"type":"string","description":"Campaign name."},"status":{"type":"string","description":"Platform status, e.g. ACTIVE, PAUSED, ENABLED (\"\" when unknown)."},"objective":{"type":"string","description":"Campaign objective (\"\" when unknown)."},"dailyBudget":{"type":["number","null"],"description":"Daily budget in account currency (major units), null when not set."},"spend":{"type":"number","description":"Spend in account currency for the date preset."},"impressions":{"type":"integer","description":"Impressions for the date preset."},"clicks":{"type":"integer","description":"Clicks for the date preset."},"results":{"type":"number","description":"Conversions the campaign optimizes for (leads/purchases), else platform conversions."},"ctr":{"type":"number","description":"Click-through rate in percent (0-100)."},"cpc":{"type":"number","description":"Cost per click in account currency."},"costPerResult":{"type":"number","description":"Spend / results in account currency (0 when no results)."},"currency":{"type":"string","description":"Account currency code (\"\" when unknown)."}},"additionalProperties":true,"required":["platform","accountId","id","name","status","objective","dailyBudget","spend","impressions","clicks","results","ctr","cpc","costPerResult","currency"]},"description":"Campaigns with metrics for the date preset, highest spend first."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (max 100)."},"total":{"type":"integer","description":"Total matching rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the (already filtered and sorted) result set."},"datePreset":{"type":"string","description":"Date preset the metrics cover, e.g. last_30d."},"accountsScanned":{"type":"integer","description":"Ad accounts actually read (max 8; Google max 3)."},"accountsAvailable":{"type":"integer","description":"Ad accounts that matched the filter."},"notes":{"type":"array","items":{"type":"string"},"description":"Caveats (accounts skipped, platform read errors); absent when none."}},"additionalProperties":true,"required":["ok","requestId","campaigns","pagination","datePreset","accountsScanned","accountsAvailable"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/campaigns/{id}":{"get":{"operationId":"get_campaign","summary":"One campaign with its settings and headline metrics","description":"One campaign with its settings and headline metrics. Ids are platform-scoped — pass the platform and accountId you got from list_campaigns.\n\nRequired scope: `campaigns.read`. Risk level: `read`.","tags":["campaigns"],"security":[{"bearerAuth":["campaigns.read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Campaign id from list_campaigns.","schema":{"type":"string","maxLength":60}},{"name":"platform","in":"query","required":false,"description":"Platform the id belongs to.","schema":{"type":"string","enum":["meta","google","dv360"]}},{"name":"accountId","in":"query","required":false,"description":"Ad account id, to avoid scanning every account.","schema":{"type":"string","maxLength":60}},{"name":"datePreset","in":"query","required":false,"description":"Reporting window.","schema":{"type":"string","enum":["today","yesterday","last_7d","last_14d","last_30d","this_month","last_month","maximum"],"default":"last_30d"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"campaign":{"type":"object","properties":{"platform":{"type":"string","enum":["meta","google","dv360"],"description":"Ad platform."},"accountId":{"type":"string","description":"Ad account id without the act_ prefix (\"\" when unknown)."},"id":{"type":"string","description":"Campaign id, platform-specific (Google gads_ prefix stripped)."},"name":{"type":"string","description":"Campaign name."},"status":{"type":"string","description":"Platform status, e.g. ACTIVE, PAUSED, ENABLED (\"\" when unknown)."},"objective":{"type":"string","description":"Campaign objective (\"\" when unknown)."},"dailyBudget":{"type":["number","null"],"description":"Daily budget in account currency (major units), null when not set."},"spend":{"type":"number","description":"Spend in account currency for the date preset."},"impressions":{"type":"integer","description":"Impressions for the date preset."},"clicks":{"type":"integer","description":"Clicks for the date preset."},"results":{"type":"number","description":"Conversions the campaign optimizes for (leads/purchases), else platform conversions."},"ctr":{"type":"number","description":"Click-through rate in percent (0-100)."},"cpc":{"type":"number","description":"Cost per click in account currency."},"costPerResult":{"type":"number","description":"Spend / results in account currency (0 when no results)."},"currency":{"type":"string","description":"Account currency code (\"\" when unknown)."}},"additionalProperties":true,"required":["platform","accountId","id","name","status","objective","dailyBudget","spend","impressions","clicks","results","ctr","cpc","costPerResult","currency"],"description":"The campaign with its metrics."},"datePreset":{"type":"string","description":"Date preset the metrics cover, e.g. last_30d."}},"additionalProperties":true,"required":["ok","requestId","campaign","datePreset"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/campaigns/{id}/performance":{"get":{"operationId":"get_campaign_performance","summary":"Just the metrics for one campaign over a date preset — spend, impressions, clicks, results, CTR, CPC, cost per result","description":"Just the metrics for one campaign over a date preset — spend, impressions, clicks, results, CTR, CPC, cost per result. Use it when you only need the numbers.\n\nRequired scope: `campaigns.read`. Risk level: `read`.","tags":["campaigns"],"security":[{"bearerAuth":["campaigns.read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Campaign id from list_campaigns.","schema":{"type":"string","maxLength":60}},{"name":"platform","in":"query","required":false,"description":"Platform the id belongs to.","schema":{"type":"string","enum":["meta","google","dv360"]}},{"name":"accountId","in":"query","required":false,"description":"Ad account id.","schema":{"type":"string","maxLength":60}},{"name":"datePreset","in":"query","required":false,"description":"Reporting window.","schema":{"type":"string","enum":["today","yesterday","last_7d","last_14d","last_30d","this_month","last_month","maximum"],"default":"last_30d"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"campaign":{"type":"object","properties":{"id":{"type":"string","description":"Campaign id."},"name":{"type":"string","description":"Campaign name."},"platform":{"type":"string","enum":["meta","google","dv360"],"description":"Ad platform."},"status":{"type":"string","description":"Platform status."},"currency":{"type":"string","description":"Account currency code."}},"additionalProperties":true,"required":["id","name","platform","status","currency"],"description":"Campaign identity."},"datePreset":{"type":"string","description":"Date preset the metrics cover, e.g. last_30d."},"metrics":{"type":"object","properties":{"spend":{"type":"number","description":"Spend."},"impressions":{"type":"integer","description":"Impressions."},"clicks":{"type":"integer","description":"Clicks."},"results":{"type":"number","description":"Optimized conversions (leads/purchases)."},"ctr":{"type":"number","description":"Click-through rate in percent."},"cpc":{"type":"number","description":"Cost per click."},"costPerResult":{"type":"number","description":"Spend / results (0 when no results)."}},"additionalProperties":true,"required":["spend","impressions","clicks","results","ctr","cpc","costPerResult"],"description":"Performance for the date preset, in account currency."}},"additionalProperties":true,"required":["ok","requestId","campaign","datePreset","metrics"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/reports/lead-sources":{"get":{"operationId":"get_lead_source_report","summary":"Lead volume and outcome grouped by source, campaign, form, page or status, over an optional date range: leads, won, lost, still open and win rate per group","description":"Lead volume and outcome grouped by source, campaign, form, page or status, over an optional date range: leads, won, lost, still open and win rate per group. Use it for \"where are our leads coming from and which convert?\".\n\nRequired scope: `reports.read`. Risk level: `read`.","tags":["reports"],"security":[{"bearerAuth":["reports.read"]}],"parameters":[{"name":"groupBy","in":"query","required":false,"description":"Grouping dimension.","schema":{"type":"string","enum":["source","campaign","form","page","status"],"default":"source"}},{"name":"status","in":"query","required":false,"description":"Restrict to one status before grouping.","schema":{"type":"string","enum":["New","Contacted","Qualified","Scheduled a Meeting","Proposal","Negotiation","Won","Lost","Unresponsive"]}},{"name":"dateFrom","in":"query","required":false,"description":"Only records at or after this ISO 8601 date/datetime (e.g. 2026-07-01).","schema":{"type":"string","maxLength":40}},{"name":"dateTo","in":"query","required":false,"description":"Only records at or before this ISO 8601 date/datetime.","schema":{"type":"string","maxLength":40}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"groupBy":{"type":"string","enum":["source","campaign","form","page","status"],"description":"Grouping applied."},"totalLeads":{"type":"integer","description":"Leads matching the filters."},"groups":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Group value (\"(none)\" when empty)."},"leads":{"type":"integer","description":"Leads in the group."},"won":{"type":"integer","description":"Leads with status Won."},"lost":{"type":"integer","description":"Leads with status Lost or Unresponsive."},"open":{"type":"integer","description":"Leads in an open status."},"winRate":{"type":"number","description":"won / leads in percent (0-100, 1 decimal)."}},"additionalProperties":true,"required":["key","leads","won","lost","open","winRate"]},"description":"Up to 100 groups, most leads first."},"sources":{"type":"object","properties":{"facebook":{"type":"object","properties":{"count":{"type":"integer","description":"Rows read from this store (0 when unavailable)."},"stale":{"type":"boolean","description":"True when the cached form leads are stale; only present when the store loaded."},"unavailable":{"type":"string","description":"Set only when the store failed to load: short reason (≤140 chars)."}},"additionalProperties":true,"required":["count"],"description":"Facebook lead-form store: rows contributed, or why it was unavailable."},"manual":{"type":"object","properties":{"count":{"type":"integer","description":"Rows read from this store (0 when unavailable)."},"unavailable":{"type":"string","description":"Set only when the store failed to load: short reason (≤140 chars)."}},"additionalProperties":true,"required":["count"],"description":"Manual / CSV-import store: rows contributed, or why it was unavailable."},"landing_page":{"type":"object","properties":{"count":{"type":"integer","description":"Rows read from this store (0 when unavailable)."},"unavailable":{"type":"string","description":"Set only when the store failed to load: short reason (≤140 chars)."}},"additionalProperties":true,"required":["count"],"description":"Landing-page submission store: rows contributed, or why it was unavailable."}},"additionalProperties":true,"required":["facebook","manual","landing_page"],"description":"Which lead stores contributed to the working set; a failed store reports `unavailable` rather than under-counting."},"dateFrom":{"type":"string","description":"The dateFrom filter echoed back (\"\" when none)."},"dateTo":{"type":"string","description":"The dateTo filter echoed back (\"\" when none)."}},"additionalProperties":true,"required":["ok","requestId","groupBy","totalLeads","groups","sources","dateFrom","dateTo"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/reports/conversions":{"get":{"operationId":"get_conversion_report","summary":"Revenue attribution over the last N days: orders and revenue credited back to the ad, email or SMS touch that produced them, using the platform's own attribution model","description":"Revenue attribution over the last N days: orders and revenue credited back to the ad, email or SMS touch that produced them, using the platform's own attribution model. Not recomputed here, so it agrees with what the app shows.\n\nRequired scope: `reports.read`. Risk level: `read`.","tags":["reports"],"security":[{"bearerAuth":["reports.read"]}],"parameters":[{"name":"days","in":"query","required":false,"description":"Look-back window in days.","schema":{"type":"integer","minimum":1,"maximum":365,"default":30}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"days":{"type":"integer","description":"Attribution window in days (1-365, default 30)."},"rows":{"type":"array","items":{"type":"object","properties":{"channel":{"type":"string","description":"Network / channel, e.g. facebook, google, email, sms."},"campaign":{"type":"string","description":"Campaign name."},"conversions":{"type":"integer","description":"Orders attributed to the campaign."},"revenue":{"type":"number","description":"Attributed revenue, 2 decimals."},"currency":{"type":"string","description":"Currency code (\"\" when unknown)."},"spend":{"type":["number","null"],"description":"Ad spend when known, else null."}},"additionalProperties":true,"required":["channel","campaign","conversions","revenue","currency","spend"]},"description":"Up to 100 attributed campaigns."},"byChannel":{"type":"array","items":{"type":"object","properties":{"channel":{"type":"string","description":"Network / channel."},"conversions":{"type":"integer","description":"Attributed orders."},"revenue":{"type":"number","description":"Attributed revenue, 2 decimals."}},"additionalProperties":true,"required":["channel","conversions","revenue"]},"description":"Attributed totals per channel, highest revenue first."},"totals":{"type":"object","properties":{"conversions":{"type":"integer","description":"Orders credited to a touch."},"revenue":{"type":"number","description":"Revenue credited to a touch."},"allConversions":{"type":"integer","description":"Every order in the window."},"allRevenue":{"type":"number","description":"Revenue of every order in the window."}},"additionalProperties":true,"required":["conversions","revenue","allConversions","allRevenue"],"description":"Attributed vs. all orders in the window."}},"additionalProperties":true,"required":["ok","requestId","days","rows","byChannel","totals"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/conversations":{"get":{"operationId":"list_conversations","summary":"Open message threads across WhatsApp, SMS, Facebook Messenger and Instagram DMs, newest first, with the last message, its time and the unread count","description":"Open message threads across WhatsApp, SMS, Facebook Messenger and Instagram DMs, newest first, with the last message, its time and the unread count. Reading never marks anything read. Channels that are not connected are skipped and listed in `notes`.\n\nRequired scope: `conversations.read`. Risk level: `read`.","tags":["conversations"],"security":[{"bearerAuth":["conversations.read"]}],"parameters":[{"name":"channel","in":"query","required":false,"description":"Restrict to one channel.","schema":{"type":"string","enum":["whatsapp","sms","facebook","instagram"]}},{"name":"unreadOnly","in":"query","required":false,"description":"Only threads with unread inbound messages.","schema":{"type":"boolean","default":false}},{"name":"query","in":"query","required":false,"description":"Substring of the contact name, or a phone number.","schema":{"type":"string","maxLength":120}},{"name":"dateFrom","in":"query","required":false,"description":"Only records at or after this ISO 8601 date/datetime (e.g. 2026-07-01).","schema":{"type":"string","maxLength":40}},{"name":"dateTo","in":"query","required":false,"description":"Only records at or before this ISO 8601 date/datetime.","schema":{"type":"string","maxLength":40}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"conversations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Channel-prefixed id (whatsapp:<phone>, sms:<phone>, facebook|instagram:<pageId>:<convId>); pass to get_conversation."},"channel":{"type":"string","enum":["whatsapp","sms","facebook","instagram"],"description":"Channel."},"contact":{"type":"object","properties":{"name":{"type":"string","description":"Display name (falls back to phone)."},"phone":{"type":"string","description":"Phone (whatsapp, sms)."},"externalId":{"type":"string","description":"Platform user id (facebook, instagram)."}},"additionalProperties":true,"required":["name"],"description":"The other party."},"lastMessage":{"type":"string","description":"Snippet of the latest message (≤200 chars)."},"lastMessageAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."},"unread":{"type":"integer","description":"Unread message count."},"messageCount":{"type":"integer","description":"WhatsApp only: messages in the thread."},"pageId":{"type":"string","description":"Facebook/Instagram only: the page the thread belongs to."}},"additionalProperties":true,"required":["id","channel","contact","lastMessage","lastMessageAt","unread"]},"description":"Inbox threads across channels, newest message first."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (max 100)."},"total":{"type":"integer","description":"Total matching rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the (already filtered and sorted) result set."},"notes":{"type":"array","items":{"type":"string"},"description":"Per-channel read errors; absent when none."}},"additionalProperties":true,"required":["ok","requestId","conversations","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/conversations/{id}":{"get":{"operationId":"get_conversation","summary":"The messages of one thread, oldest to newest, each marked inbound or outbound","description":"The messages of one thread, oldest to newest, each marked inbound or outbound. Use the composite id from list_conversations (for example \"whatsapp:+972…\"). Reading does not mark the thread read and does not send anything.\n\nRequired scope: `conversations.read`. Risk level: `read`.","tags":["conversations"],"security":[{"bearerAuth":["conversations.read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Composite conversation id from list_conversations.","schema":{"type":"string","maxLength":200}},{"name":"limit","in":"query","required":false,"description":"Maximum messages to return (most recent).","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"conversation":{"type":"object","properties":{"id":{"type":"string","description":"The id requested."},"channel":{"type":"string","enum":["whatsapp","sms","facebook","instagram"],"description":"Channel."},"contact":{"type":"object","properties":{"name":{"type":"string","description":"Display name (whatsapp)."},"phone":{"type":"string","description":"Phone."}},"additionalProperties":true,"required":["phone"],"description":"The other party (whatsapp, sms)."},"pageId":{"type":"string","description":"Facebook/Instagram only: the page id."}},"additionalProperties":true,"required":["id","channel"],"description":"Thread identity."},"messages":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string","description":"ISO 8601 (\"\" when unknown)."},"direction":{"type":"string","enum":["inbound","outbound"],"description":"inbound = from the contact, outbound = sent by the workspace."},"text":{"type":"string","description":"Message text (≤2000 chars)."},"type":{"type":"string","description":"WhatsApp only: message type, e.g. text, image."},"from":{"type":"string","description":"Facebook/Instagram only: sender label."}},"additionalProperties":true,"required":["at","direction","text"]},"description":"The last `limit` messages (max 100), oldest first."},"optedOut":{"type":"boolean","description":"SMS only: true when the number opted out."}},"additionalProperties":true,"required":["ok","requestId","conversation","messages"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/automations":{"get":{"operationId":"list_automations","summary":"Marketing automations (journeys) in this workspace: name, whether enabled, what triggers entry and which step types it runs (email, SMS, WhatsApp, wait, filter, ad audience)","description":"Marketing automations (journeys) in this workspace: name, whether enabled, what triggers entry and which step types it runs (email, SMS, WhatsApp, wait, filter, ad audience). These are this platform's automated agents — it has no separate \"AI agent\" object.\n\nRequired scope: `agents.read`. Risk level: `read`.","tags":["agents"],"security":[{"bearerAuth":["agents.read"]}],"parameters":[{"name":"enabledOnly","in":"query","required":false,"description":"Only automations currently enabled.","schema":{"type":"boolean","default":false}},{"name":"query","in":"query","required":false,"description":"Substring of the automation name.","schema":{"type":"string","maxLength":120}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"automations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Automation (journey) id."},"name":{"type":"string","description":"Automation name."},"enabled":{"type":"boolean","description":"True when the journey is switched on."},"entryType":{"type":"string","description":"Entry trigger type (\"\" when unknown)."},"stepTypes":{"type":"array","items":{"type":"string"},"description":"Distinct step types used (email, sms, whatsapp, wait, audience, …)."},"stepCount":{"type":"integer","description":"Number of steps walked (branches included, capped)."},"owner":{"type":"string","description":"Owner email (\"\" when unknown)."},"createdAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."},"updatedAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."}},"additionalProperties":true,"required":["id","name","enabled","entryType","stepTypes","stepCount","owner","createdAt","updatedAt"]},"description":"Automations (journeys), most recently updated first."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (max 100)."},"total":{"type":"integer","description":"Total matching rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the (already filtered and sorted) result set."}},"additionalProperties":true,"required":["ok","requestId","automations","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/automations/{id}":{"get":{"operationId":"get_automation","summary":"One automation with its run statistics: contacts entered and completed, emails and SMS sent, conversions, orders, opens and unsubscribes","description":"One automation with its run statistics: contacts entered and completed, emails and SMS sent, conversions, orders, opens and unsubscribes.\n\nRequired scope: `agents.read`. Risk level: `read`.","tags":["agents"],"security":[{"bearerAuth":["agents.read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Automation id from list_automations.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"automation":{"type":"object","properties":{"id":{"type":"string","description":"Automation (journey) id."},"name":{"type":"string","description":"Automation name."},"enabled":{"type":"boolean","description":"True when the journey is switched on."},"entryType":{"type":"string","description":"Entry trigger type (\"\" when unknown)."},"stepTypes":{"type":"array","items":{"type":"string"},"description":"Distinct step types used (email, sms, whatsapp, wait, audience, …)."},"stepCount":{"type":"integer","description":"Number of steps walked (branches included, capped)."},"owner":{"type":"string","description":"Owner email (\"\" when unknown)."},"createdAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."},"updatedAt":{"type":"string","description":"ISO 8601 (\"\" when unknown)."},"stats":{"type":["object","null"],"properties":{"started":{"type":"integer","description":"Contacts that entered the journey."},"completed":{"type":"integer","description":"Contacts that finished it."},"emailsSent":{"type":"integer","description":"Emails sent."},"smsSent":{"type":"integer","description":"SMS sent."},"conversions":{"type":"integer","description":"Conversions attributed."},"orders":{"type":"integer","description":"Orders attributed."},"opens":{"type":"integer","description":"Email opens."},"unsubscribes":{"type":"integer","description":"Unsubscribes."}},"additionalProperties":true,"required":["started","completed","emailsSent","smsSent","conversions","orders","opens","unsubscribes"],"description":"Lifetime counters; null when the stats read failed."}},"additionalProperties":true,"required":["id","name","enabled","entryType","stepTypes","stepCount","owner","createdAt","updatedAt","stats"],"description":"The automation with its lifetime stats."}},"additionalProperties":true,"required":["ok","requestId","automation"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/leads/{id}/update":{"post":{"operationId":"update_lead","summary":"Change a lead's pipeline status, owner, rating or the board's Due Date","description":"Change a lead's pipeline status, owner, rating or the board's Due Date. Supply only the fields you want to change; the rest are left alone. Returns before and after so the change is auditable. Works for leads from any source — the update is routed to the store that source uses, so it shows up in the app. Never creates a lead.\n\nRequired scope: `leads.write`. Risk level: `write`.","tags":["leads"],"security":[{"bearerAuth":["leads.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Lead id from search_leads.","schema":{"type":"string","maxLength":80}},{"name":"status","in":"query","required":false,"description":"New pipeline status.","schema":{"type":"string","enum":["New","Contacted","Qualified","Scheduled a Meeting","Proposal","Negotiation","Won","Lost","Unresponsive"]}},{"name":"owner","in":"query","required":false,"description":"New owner (their email). Pass an empty string to unassign.","schema":{"type":"string","maxLength":120}},{"name":"rating","in":"query","required":false,"description":"Star rating, 0-5.","schema":{"type":"integer","minimum":0,"maximum":5}},{"name":"dueDate","in":"query","required":false,"description":"The board's Due Date, yyyy-mm-dd, or \"\" to clear.","schema":{"type":"string","maxLength":40}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["lead"],"description":"Always \"lead\"."},"targetId":{"type":"string","description":"Id of the updated lead."},"updated":{"type":"boolean","description":"Always true on success."},"lead":{"type":"object","properties":{"id":{"type":"string","description":"Lead id."},"source":{"type":"string","enum":["facebook","manual","landing_page"],"description":"Where the lead came from: facebook | manual | landing_page."},"name":{"type":"string","description":"Lead name."},"email":{"type":"string","description":"Lead email, \"\" when none."}},"additionalProperties":true,"required":["id","source","name","email"],"description":"Identity of the updated lead."},"before":{"type":"object","properties":{"status":{"type":"string","description":"Pipeline status, e.g. New, Contacted, Qualified, Won, Lost."},"owner":{"type":"string","description":"Assigned owner, \"\" when unassigned."},"rating":{"type":"number","description":"Star rating 0-5."},"dueDate":{"type":"string","description":"The board Due Date (yyyy-mm-dd), \"\" when none."}},"additionalProperties":true,"required":["status","owner","rating","dueDate"],"description":"status / owner / rating / dueDate before the change."},"after":{"type":"object","properties":{"status":{"type":"string","description":"Pipeline status, e.g. New, Contacted, Qualified, Won, Lost."},"owner":{"type":"string","description":"Assigned owner, \"\" when unassigned."},"rating":{"type":"number","description":"Star rating 0-5."},"dueDate":{"type":"string","description":"The board Due Date (yyyy-mm-dd), \"\" when none."}},"additionalProperties":true,"required":["status","owner","rating","dueDate"],"description":"status / owner / rating / dueDate after the change."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","updated","lead","before","after"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/leads/{id}/status":{"post":{"operationId":"update_lead_status","summary":"Move one lead to a different pipeline status","description":"Move one lead to a different pipeline status. A focused alias for update_lead when status is all you are changing.\n\nRequired scope: `leads.write`. Risk level: `write`.","tags":["leads"],"security":[{"bearerAuth":["leads.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Lead id from search_leads.","schema":{"type":"string","maxLength":80}},{"name":"status","in":"query","required":true,"description":"New pipeline status.","schema":{"type":"string","enum":["New","Contacted","Qualified","Scheduled a Meeting","Proposal","Negotiation","Won","Lost","Unresponsive"]}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["lead"],"description":"Always \"lead\"."},"targetId":{"type":"string","description":"Id of the updated lead."},"updated":{"type":"boolean","description":"Always true on success."},"lead":{"type":"object","properties":{"id":{"type":"string","description":"Lead id."},"source":{"type":"string","enum":["facebook","manual","landing_page"],"description":"Where the lead came from: facebook | manual | landing_page."},"name":{"type":"string","description":"Lead name."},"email":{"type":"string","description":"Lead email, \"\" when none."}},"additionalProperties":true,"required":["id","source","name","email"],"description":"Identity of the updated lead."},"before":{"type":"object","properties":{"status":{"type":"string","description":"Pipeline status, e.g. New, Contacted, Qualified, Won, Lost."},"owner":{"type":"string","description":"Assigned owner, \"\" when unassigned."},"rating":{"type":"number","description":"Star rating 0-5."},"dueDate":{"type":"string","description":"The board Due Date (yyyy-mm-dd), \"\" when none."}},"additionalProperties":true,"required":["status","owner","rating","dueDate"],"description":"status / owner / rating / dueDate before the change."},"after":{"type":"object","properties":{"status":{"type":"string","description":"Pipeline status, e.g. New, Contacted, Qualified, Won, Lost."},"owner":{"type":"string","description":"Assigned owner, \"\" when unassigned."},"rating":{"type":"number","description":"Star rating 0-5."},"dueDate":{"type":"string","description":"The board Due Date (yyyy-mm-dd), \"\" when none."}},"additionalProperties":true,"required":["status","owner","rating","dueDate"],"description":"status / owner / rating / dueDate after the change."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","updated","lead","before","after"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/leads/{id}/owner":{"post":{"operationId":"assign_lead_owner","summary":"Assign a lead to a team member by their email address, or unassign it with an empty string","description":"Assign a lead to a team member by their email address, or unassign it with an empty string.\n\nRequired scope: `leads.write`. Risk level: `write`.","tags":["leads"],"security":[{"bearerAuth":["leads.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Lead id from search_leads.","schema":{"type":"string","maxLength":80}},{"name":"owner","in":"query","required":true,"description":"Owner email, or \"\" to unassign.","schema":{"type":"string","maxLength":120}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["lead"],"description":"Always \"lead\"."},"targetId":{"type":"string","description":"Id of the updated lead."},"updated":{"type":"boolean","description":"Always true on success."},"lead":{"type":"object","properties":{"id":{"type":"string","description":"Lead id."},"source":{"type":"string","enum":["facebook","manual","landing_page"],"description":"Where the lead came from: facebook | manual | landing_page."},"name":{"type":"string","description":"Lead name."},"email":{"type":"string","description":"Lead email, \"\" when none."}},"additionalProperties":true,"required":["id","source","name","email"],"description":"Identity of the updated lead."},"before":{"type":"object","properties":{"status":{"type":"string","description":"Pipeline status, e.g. New, Contacted, Qualified, Won, Lost."},"owner":{"type":"string","description":"Assigned owner, \"\" when unassigned."},"rating":{"type":"number","description":"Star rating 0-5."},"dueDate":{"type":"string","description":"The board Due Date (yyyy-mm-dd), \"\" when none."}},"additionalProperties":true,"required":["status","owner","rating","dueDate"],"description":"status / owner / rating / dueDate before the change."},"after":{"type":"object","properties":{"status":{"type":"string","description":"Pipeline status, e.g. New, Contacted, Qualified, Won, Lost."},"owner":{"type":"string","description":"Assigned owner, \"\" when unassigned."},"rating":{"type":"number","description":"Star rating 0-5."},"dueDate":{"type":"string","description":"The board Due Date (yyyy-mm-dd), \"\" when none."}},"additionalProperties":true,"required":["status","owner","rating","dueDate"],"description":"status / owner / rating / dueDate after the change."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","updated","lead","before","after"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/leads/{id}/notes":{"post":{"operationId":"add_lead_note","summary":"Add a note to a lead's timeline","description":"Add a note to a lead's timeline. Set kind to log something that happened — a call, an email, a meeting — so it appears as that activity rather than a plain note, and set occurredAt to back-date it.\n\nRequired scope: `notes.write`. Risk level: `write`.","tags":["notes"],"security":[{"bearerAuth":["notes.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Lead id from search_leads.","schema":{"type":"string","maxLength":80}},{"name":"text","in":"query","required":true,"description":"The note body.","schema":{"type":"string","maxLength":5000}},{"name":"kind","in":"query","required":false,"description":"What this records. Defaults to note.","schema":{"type":"string","enum":["note","call","email","meeting","linkedin","sms","other"]}},{"name":"occurredAt","in":"query","required":false,"description":"ISO 8601 time it actually happened, if not now.","schema":{"type":"string","maxLength":40}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["lead"],"description":"Always \"lead\"."},"targetId":{"type":"string","description":"Id of the lead the note was attached to."},"created":{"type":"boolean","description":"Always true on success."},"note":{"type":"object","properties":{"id":{"type":"string","description":"Note id, \"\" if the store did not return one."},"kind":{"type":"string","enum":["note","call","email","meeting","linkedin","sms","other"],"description":"Timeline chip kind."},"text":{"type":"string","description":"First 200 characters of the note text."},"createdAt":{"type":"string","description":"ISO 8601 creation time."}},"additionalProperties":true,"required":["id","kind","text","createdAt"],"description":"The saved timeline entry."},"lead":{"type":"object","properties":{"id":{"type":"string","description":"Lead id."},"name":{"type":"string","description":"Lead name."},"email":{"type":"string","description":"Lead email, \"\" when none."}},"additionalProperties":true,"required":["id","name","email"],"description":"Identity of the lead."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","created","note","lead"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/tasks/{id}/update":{"post":{"operationId":"update_task","summary":"Change a task's title, due date, owner, priority or done state","description":"Change a task's title, due date, owner, priority or done state. Only the fields you supply change.\n\nRequired scope: `tasks.write`. Risk level: `write`.","tags":["tasks"],"security":[{"bearerAuth":["tasks.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Task id from list_tasks.","schema":{"type":"string","maxLength":80}},{"name":"title","in":"query","required":false,"description":"New title.","schema":{"type":"string","maxLength":200}},{"name":"dueDate","in":"query","required":false,"description":"New ISO 8601 due date, or \"\" to clear it.","schema":{"type":"string","maxLength":40}},{"name":"owner","in":"query","required":false,"description":"New owner email, or \"\" to unassign.","schema":{"type":"string","maxLength":120}},{"name":"priority","in":"query","required":false,"description":"New priority.","schema":{"type":"string","enum":["low","normal","high","urgent"]}},{"name":"done","in":"query","required":false,"description":"Mark done or not done.","schema":{"type":"boolean"}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["task"],"description":"Always \"task\"."},"targetId":{"type":"string","description":"Id of the updated task."},"updated":{"type":"boolean","description":"Always true on success."},"task":{"type":"object","properties":{"id":{"type":"string","description":"Task id."},"title":{"type":"string","description":"Task title."},"done":{"type":"boolean","description":"True when the task is completed."},"priority":{"type":"string","description":"API priority: low | normal | high | urgent, or \"\" when unset."},"priorityLabel":{"type":"string","description":"Priority as stored on the board (e.g. Medium), \"\" when unset."},"owner":{"type":"string","description":"Assignee (email or name), \"\" when unassigned."},"dueAt":{"type":"string","description":"Due date/time as ISO 8601 (end of day when no time), \"\" when none."},"relatedTo":{"type":["object","null"],"properties":{"type":{"type":"string","description":"Entity type (e.g. contact, deal, company)."},"id":{"type":"string","description":"Entity id."}},"additionalProperties":true,"required":["type","id"],"description":"Linked CRM entity, null when the task is not linked."}},"additionalProperties":true,"required":["id","title","done","priority","priorityLabel","owner","dueAt","relatedTo"],"description":"The task as list_tasks would return it."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","updated","task"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/tasks/{id}/complete":{"post":{"operationId":"complete_task","summary":"Mark a task done","description":"Mark a task done. Calling it on an already-completed task changes nothing and says so.\n\nRequired scope: `tasks.write`. Risk level: `write`.","tags":["tasks"],"security":[{"bearerAuth":["tasks.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Task id from list_tasks.","schema":{"type":"string","maxLength":80}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["task"],"description":"Always \"task\"."},"targetId":{"type":"string","description":"Task id."},"updated":{"type":"boolean","description":"False when the task was already done (nothing written)."},"alreadyDone":{"type":"boolean","description":"Present (true) only when the task was already completed."},"task":{"type":"object","properties":{"id":{"type":"string","description":"Task id."},"title":{"type":"string","description":"Task title."},"done":{"type":"boolean","description":"True when the task is completed."},"priority":{"type":"string","description":"API priority: low | normal | high | urgent, or \"\" when unset."},"priorityLabel":{"type":"string","description":"Priority as stored on the board (e.g. Medium), \"\" when unset."},"owner":{"type":"string","description":"Assignee (email or name), \"\" when unassigned."},"dueAt":{"type":"string","description":"Due date/time as ISO 8601 (end of day when no time), \"\" when none."},"relatedTo":{"type":["object","null"],"properties":{"type":{"type":"string","description":"Entity type (e.g. contact, deal, company)."},"id":{"type":"string","description":"Entity id."}},"additionalProperties":true,"required":["type","id"],"description":"Linked CRM entity, null when the task is not linked."}},"additionalProperties":true,"required":["id","title","done","priority","priorityLabel","owner","dueAt","relatedTo"],"description":"The task as list_tasks would return it."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","updated","task"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/drafts/email":{"post":{"operationId":"create_email_draft","summary":"Write an email DRAFT into FORTVISION","description":"Write an email DRAFT into FORTVISION. It appears under Email → Drafts for a human to review, style and send — this tool never sends anything and never picks recipients. Give it plain content (subject, headline, body paragraphs separated by blank lines, an optional button) and it builds a valid email in the editor's format. Use direction \"rtl\" for Hebrew or Arabic.\n\nRequired scope: `messages.draft`. Risk level: `write`.","tags":["messages"],"security":[{"bearerAuth":["messages.draft"]}],"parameters":[{"name":"subject","in":"query","required":true,"description":"Subject line.","schema":{"type":"string","maxLength":200}},{"name":"name","in":"query","required":false,"description":"Internal name for the draft. Defaults to the subject.","schema":{"type":"string","maxLength":120}},{"name":"preheader","in":"query","required":false,"description":"Preview text shown after the subject in most inboxes.","schema":{"type":"string","maxLength":200}},{"name":"headline","in":"query","required":false,"description":"Large headline at the top of the email.","schema":{"type":"string","maxLength":200}},{"name":"body","in":"query","required":false,"description":"Body copy. Separate paragraphs with a blank line; each becomes its own block.","schema":{"type":"string","maxLength":20000}},{"name":"buttonLabel","in":"query","required":false,"description":"Call-to-action button text.","schema":{"type":"string","maxLength":60}},{"name":"buttonUrl","in":"query","required":false,"description":"Where the button links (http/https).","schema":{"type":"string","maxLength":600}},{"name":"direction","in":"query","required":false,"description":"Text direction. Use rtl for Hebrew/Arabic.","schema":{"type":"string","enum":["ltr","rtl"],"default":"ltr"}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["email_draft"],"description":"Always \"email_draft\"."},"targetId":{"type":"string","description":"Draft id."},"created":{"type":"boolean","description":"Always true on success."},"draft":{"type":"object","properties":{"id":{"type":"string","description":"Draft id (t_…)."},"channel":{"type":"string","enum":["email"],"description":"Always \"email\"."},"name":{"type":"string","description":"Draft name (falls back to the subject)."},"subject":{"type":"string","description":"Email subject."},"blocks":{"type":"integer","description":"Number of editor blocks generated (heading, paragraphs, button)."},"updatedAt":{"type":"string","description":"ISO 8601 save time."}},"additionalProperties":true,"required":["id","channel","name","subject","blocks","updatedAt"],"description":"The saved draft (nothing is sent)."},"whereToFind":{"type":"string","description":"Where a human finds the draft in the app."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","created","draft","whereToFind"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/drafts/sms":{"post":{"operationId":"create_sms_draft","summary":"Save an SMS DRAFT the SMS composer can pick up","description":"Save an SMS DRAFT the SMS composer can pick up. Never sends and never selects recipients. The response reports the character count and how many 160-character segments the message will cost.\n\nRequired scope: `messages.draft`. Risk level: `write`.","tags":["messages"],"security":[{"bearerAuth":["messages.draft"]}],"parameters":[{"name":"message","in":"query","required":true,"description":"The SMS body.","schema":{"type":"string","maxLength":1600}},{"name":"name","in":"query","required":false,"description":"Internal name for the draft.","schema":{"type":"string","maxLength":120}},{"name":"senderProfileId","in":"query","required":false,"description":"Sender profile to use, from the SMS senders list.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["sms_draft"],"description":"Always \"sms_draft\"."},"targetId":{"type":"string","description":"Draft id."},"created":{"type":"boolean","description":"Always true on success."},"draft":{"type":"object","properties":{"id":{"type":"string","description":"Draft id (d_…)."},"channel":{"type":"string","enum":["sms"],"description":"Always \"sms\"."},"name":{"type":"string","description":"Draft name (first 40 chars of the message when not supplied)."},"message":{"type":"string","description":"Full message text (≤ 1600 chars)."},"characters":{"type":"integer","description":"Message length in characters."},"segments":{"type":"integer","description":"SMS segments at 160 chars each."},"updatedAt":{"type":"string","description":"ISO 8601 save time."}},"additionalProperties":true,"required":["id","channel","name","message","characters","segments","updatedAt"],"description":"The saved draft (nothing is sent)."},"whereToFind":{"type":"string","description":"Where a human finds the draft in the app."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","created","draft","whereToFind"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/drafts/whatsapp":{"post":{"operationId":"create_whatsapp_draft","summary":"Save a WhatsApp DRAFT into the WhatsApp composer, where it appears under Drafts for a human to finish and send","description":"Save a WhatsApp DRAFT into the WhatsApp composer, where it appears under Drafts for a human to finish and send. Never sends. WhatsApp delivers only approved templates outside a 24-hour service window, so a draft names a template rather than free text — call list_whatsapp_templates first — and templateVariables fill its placeholders in order.\n\nRequired scope: `messages.draft`. Risk level: `write`.","tags":["messages"],"security":[{"bearerAuth":["messages.draft"]}],"parameters":[{"name":"templateName","in":"query","required":true,"description":"Approved template name (or id) from list_whatsapp_templates.","schema":{"type":"string","maxLength":120}},{"name":"templateVariables","in":"query","required":false,"description":"Values for the template placeholders, in order.","schema":{"type":"array","maxItems":10,"items":{"type":"string"}}},{"name":"name","in":"query","required":false,"description":"Ignored — the draft is named after its template, matching the composer.","schema":{"type":"string","maxLength":120}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["whatsapp_draft"],"description":"Always \"whatsapp_draft\"."},"targetId":{"type":"string","description":"Draft id."},"created":{"type":"boolean","description":"Always true on success."},"draft":{"type":"object","properties":{"id":{"type":"string","description":"Draft id (wd_…)."},"channel":{"type":"string","enum":["whatsapp"],"description":"Always \"whatsapp\"."},"name":{"type":"string","description":"Draft name (= the template name)."},"templateName":{"type":"string","description":"Approved template name."},"templateId":{"type":"string","description":"Template id the composer selects by."},"body":{"type":"string","description":"Template body text (≤ 1000 chars), \"\" when the template has none."},"variables":{"type":"integer","description":"Number of template variables supplied."},"updatedAt":{"type":"string","description":"ISO 8601 save time."}},"additionalProperties":true,"required":["id","channel","name","templateName","templateId","body","variables","updatedAt"],"description":"The saved draft (nothing is sent)."},"note":{"type":"string","description":"Only when fewer variables were supplied than the template takes."},"whereToFind":{"type":"string","description":"Where a human finds the draft in the app."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","created","draft","whereToFind"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/drafts":{"get":{"operationId":"list_message_drafts","summary":"List saved email, SMS and WhatsApp drafts, newest first, marking which were created through this API","description":"List saved email, SMS and WhatsApp drafts, newest first, marking which were created through this API. Use it to find a draft id before reading it or sending it.\n\nRequired scope: `messages.draft`. Risk level: `read`.","tags":["messages"],"security":[{"bearerAuth":["messages.draft"]}],"parameters":[{"name":"channel","in":"query","required":false,"description":"Restrict to one channel.","schema":{"type":"string","enum":["email","sms","whatsapp"]}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"drafts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Draft id."},"channel":{"type":"string","enum":["email","sms","whatsapp"],"description":"Draft channel."},"name":{"type":"string","description":"Draft name."},"subject":{"type":"string","description":"Email drafts only: subject line."},"preview":{"type":"string","description":"SMS drafts only: first 200 chars of the message."},"templateId":{"type":"string","description":"WhatsApp drafts only: template id."},"createdVia":{"type":"string","description":"\"api\" when created through this API, otherwise \"app\"."},"updatedAt":{"type":"string","description":"ISO 8601 last save time, \"\" when unknown."}},"additionalProperties":true,"required":["id","channel","name","createdVia","updatedAt"],"description":"One draft summary row."},"description":"Drafts across the requested channel(s), newest first."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number returned."},"pageSize":{"type":"integer","description":"Rows per page."},"total":{"type":"integer","description":"Total rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page cursor for the list."}},"additionalProperties":true,"required":["ok","requestId","drafts","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/drafts/{id}":{"get":{"operationId":"get_message_draft","summary":"Read one draft in full — for email, its subject and every content block; for SMS and WhatsApp, the message body","description":"Read one draft in full — for email, its subject and every content block; for SMS and WhatsApp, the message body.\n\nRequired scope: `messages.draft`. Risk level: `read`.","tags":["messages"],"security":[{"bearerAuth":["messages.draft"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Draft id from list_message_drafts.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"draft":{"type":"object","properties":{"id":{"type":"string","description":"Draft id."},"channel":{"type":"string","enum":["email","sms","whatsapp"],"description":"Draft channel."},"name":{"type":"string","description":"Draft name."},"updatedAt":{"type":"string","description":"ISO 8601 last save time, \"\" when unknown."},"subject":{"type":"string","description":"email only: subject line."},"preheader":{"type":"string","description":"email only: preheader text, \"\" when none."},"content":{"type":"array","items":{"type":"object","properties":{"type":{"description":"Block type, e.g. heading, text, button."},"text":{"type":"string","description":"Block text (≤ 2000 chars), \"\" when none."},"href":{"type":"string","description":"Button link, \"\" for non-button blocks."}},"additionalProperties":true,"required":["text","href"],"description":"One editor block."},"description":"email only: the editor blocks in order."},"templateId":{"type":"string","description":"whatsapp only: template id."},"variables":{"type":"array","items":{"type":"string","description":"Variable value."},"description":"whatsapp only: template variable values in order."},"requireApproval":{"type":"boolean","description":"whatsapp only: whether sending requires client approval."},"message":{"type":"string","description":"sms only: message text (≤ 2000 chars)."}},"additionalProperties":true,"required":["id","channel","name","updatedAt"],"description":"The draft; which keys appear depends on `channel`."}},"additionalProperties":true,"required":["ok","requestId","draft"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/campaigns/email/send":{"post":{"operationId":"send_email_campaign","summary":"Send an existing email draft to an audience","description":"Send an existing email draft to an audience. PREVIEW FIRST: called without confirm it changes nothing and reports exactly who would receive it, how many were removed as unsubscribed or bounced, and the sending address. Unsubscribed, bounced and complained addresses are always excluded and an unsubscribe link is always added. Create the draft with create_email_draft first; this tool never writes content.\n\nRequired scope: `messages.send`. Risk level: `high`.","tags":["messages"],"security":[{"bearerAuth":["messages.send"]}],"parameters":[{"name":"draftId","in":"query","required":true,"description":"Email draft id from list_message_drafts.","schema":{"type":"string","maxLength":80}},{"name":"leadIds","in":"query","required":false,"description":"Exact leads to send to. Most precise option.","schema":{"type":"array","maxItems":500,"items":{"type":"string"}}},{"name":"status","in":"query","required":false,"description":"Send to every lead currently in this pipeline status.","schema":{"type":"string","enum":["New","Contacted","Qualified","Scheduled a Meeting","Proposal","Negotiation","Won","Lost","Unresponsive"]}},{"name":"audience","in":"query","required":false,"description":"Set to \"all_leads\" to reach every lead with a usable email address. Still capped and still previewed.","schema":{"type":"string","enum":["all_leads"]}},{"name":"fromEmail","in":"query","required":false,"description":"Verified sending address. Defaults to the workspace's first verified identity.","schema":{"type":"string","maxLength":160}},{"name":"fromName","in":"query","required":false,"description":"Display name shown as the sender.","schema":{"type":"string","maxLength":80}},{"name":"replyTo","in":"query","required":false,"description":"Reply-to address.","schema":{"type":"string","maxLength":160}},{"name":"sendAt","in":"query","required":false,"description":"ISO 8601 time to send. Defaults to about a minute from now.","schema":{"type":"string","maxLength":40}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"action":{"type":"string","enum":["send_email_campaign"],"description":"Preview only: the action being previewed."},"targetType":{"type":"string","enum":["email_draft","email_campaign"],"description":"email_draft on preview, email_campaign once queued."},"targetId":{"type":"string","description":"Draft id on preview; campaign id once queued."},"draft":{"type":"object","properties":{"id":{"type":"string","description":"Draft id."},"name":{"type":"string","description":"Draft name."},"subject":{"type":"string","description":"Subject line."}},"additionalProperties":true,"required":["id","name","subject"],"description":"Preview only: the draft that would be sent."},"from":{"type":"object","properties":{"email":{"type":"string","description":"From address."},"name":{"type":"string","description":"From display name (\"\" when none)."}},"additionalProperties":true,"required":["email","name"],"description":"Verified sending identity."},"audience":{"type":"object","properties":{"matched":{"type":"integer","description":"Leads matched by leadIds / status / audience."},"missingAddress":{"type":"integer","description":"Matched leads with no address on this channel."},"invalidAddress":{"type":"integer","description":"Addresses that failed format validation and were dropped."},"duplicatesRemoved":{"type":"integer","description":"Duplicate addresses collapsed to one."},"suppressed":{"type":"integer","description":"Removed as unsubscribed, bounced, complained or STOP."},"willReceive":{"type":"integer","description":"Final recipient count."}},"additionalProperties":true,"required":["matched","missingAddress","invalidAddress","duplicatesRemoved","suppressed","willReceive"],"description":"Audience accounting after suppression: how many matched and how many will actually receive."},"sampleRecipients":{"type":"array","items":{"type":"string"},"description":"Preview only: up to 5 recipient emails."},"sendAt":{"type":"string","description":"Preview only: ISO 8601 send time, or \"immediately\"."},"htmlBytes":{"type":"integer","description":"Preview only: rendered HTML size in bytes."},"warnings":{"type":"array","items":{"type":"string"},"description":"Plain-language cautions to show before confirming."},"sent":{"type":"boolean","description":"True once the campaign is queued."},"campaignId":{"type":"string","description":"Queued campaign id (camp_api_…)."},"scheduledFor":{"type":"string","description":"ISO 8601 time the send is scheduled for."},"recipients":{"type":"integer","description":"Recipients queued."},"subject":{"type":"string","description":"Subject line as queued."},"jobs":{"description":"Number of send jobs the queue split this into (from the scheduler)."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","from","audience"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/outreach/sequences":{"get":{"operationId":"list_email_sequences","summary":"List the outreach email sequences (multi-step cadences sent from the connected Gmail/Outlook mailboxes by the platform's sequence engine): id, name, status (running/paused), step subjects and day offsets, recipient/pending/replied counts, sending mailbox and daily cap","description":"List the outreach email sequences (multi-step cadences sent from the connected Gmail/Outlook mailboxes by the platform's sequence engine): id, name, status (running/paused), step subjects and day offsets, recipient/pending/replied counts, sending mailbox and daily cap.\n\nRequired scope: `campaigns.read`. Risk level: `read`.","tags":["campaigns"],"security":[{"bearerAuth":["campaigns.read"]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"sequences":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Sequence id."},"name":{"type":"string","description":"Sequence name."},"status":{"type":"string","description":"Sequence state, e.g. \"running\" or \"paused\"."},"steps":{"type":"array","items":{"type":"object","properties":{"n":{"type":"integer","description":"1-based step number."},"type":{"type":"string","description":"Step channel: email, sms, whatsapp or task."},"subject":{"type":"string","description":"Email subject (\"\" for non-email steps)."},"delayDays":{"type":"number","description":"Days after the previous step."}},"additionalProperties":true,"required":["n","type","subject","delayDays"]},"description":"Cadence steps in order."},"recipients":{"type":"integer","description":"Enrolled recipients."},"pending":{"type":"integer","description":"Recipients not done and not replied."},"replied":{"type":"integer","description":"Recipients who replied."},"fromAddr":{"type":"string","description":"Sending mailbox, \"__rotate__\", or \"(default mailbox)\"."},"dailyCap":{"type":"number","description":"Max sequence emails per day."},"stopOnReply":{"type":"boolean","description":"Cadence stops for a recipient who replies."},"stats":{"type":"object","additionalProperties":true,"description":"Cumulative counters, e.g. { sent, replies, opens }."},"createdAt":{"type":"number","description":"Creation time, epoch milliseconds."}},"additionalProperties":true,"required":["id","name","status","steps","recipients","pending","replied","fromAddr","stopOnReply","stats"]},"description":"Every outreach sequence in the workspace."}},"additionalProperties":true,"required":["ok","requestId","sequences"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/outreach/sequences/create":{"post":{"operationId":"create_email_sequence","summary":"Create an outreach email SEQUENCE — a multi-step cadence sent from a connected mailbox over days","description":"Create an outreach email SEQUENCE — a multi-step cadence sent from a connected mailbox over days. It is created PAUSED: nothing sends until start_email_sequence is confirmed (or Start in the Sequences tab), so creating it is reversible. steps: up to 8 of {subject, body (plain text ok), delayDays — days AFTER the previous step, first step usually 0}. recipients: up to 500 of {email, name?}. from: a connected mailbox address or \"__rotate__\" (default) to rotate across all connected mailboxes by remaining warm-up budget. Replies and bounces automatically stop the cadence for that recipient (stopOnReply defaults true).\n\nRequired scope: `messages.draft`. Risk level: `write`.","tags":["messages"],"security":[{"bearerAuth":["messages.draft"]}],"parameters":[{"name":"name","in":"query","required":true,"description":"Sequence name.","schema":{"type":"string","maxLength":120}},{"name":"steps","in":"query","required":true,"description":"Cadence steps in order. Each: { subject (required on first step), body (plain text or simple HTML), delayDays (0-60, days after the PREVIOUS step) }.","schema":{"type":"array","maxItems":8,"items":{"type":"object"}}},{"name":"recipients","in":"query","required":true,"description":"Who to enroll. Each: { email (required), name }.","schema":{"type":"array","maxItems":500,"items":{"type":"object"}}},{"name":"from","in":"query","required":false,"description":"Sending mailbox address, or \"__rotate__\" (default) to rotate across connected mailboxes.","schema":{"type":"string","maxLength":160}},{"name":"dailyCap","in":"query","required":false,"description":"Max sequence emails per day (1-100, default 20). Per-mailbox warm-up caps still apply on top.","schema":{"type":"number"}},{"name":"stopOnReply","in":"query","required":false,"description":"Stop the cadence for a recipient when they reply. Default true.","schema":{"type":"boolean"}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"id":{"type":"string","description":"Sequence id."},"name":{"type":"string","description":"Sequence name."},"status":{"type":"string","description":"Sequence state, e.g. \"running\" or \"paused\"."},"steps":{"type":"array","items":{"type":"object","properties":{"n":{"type":"integer","description":"1-based step number."},"type":{"type":"string","description":"Step channel: email, sms, whatsapp or task."},"subject":{"type":"string","description":"Email subject (\"\" for non-email steps)."},"delayDays":{"type":"number","description":"Days after the previous step."}},"additionalProperties":true,"required":["n","type","subject","delayDays"]},"description":"Cadence steps in order."},"recipients":{"type":"integer","description":"Enrolled recipients."},"pending":{"type":"integer","description":"Recipients not done and not replied."},"replied":{"type":"integer","description":"Recipients who replied."},"fromAddr":{"type":"string","description":"Sending mailbox, \"__rotate__\", or \"(default mailbox)\"."},"dailyCap":{"type":"number","description":"Max sequence emails per day."},"stopOnReply":{"type":"boolean","description":"Cadence stops for a recipient who replies."},"stats":{"type":"object","additionalProperties":true,"description":"Cumulative counters, e.g. { sent, replies, opens }."},"createdAt":{"type":"number","description":"Creation time, epoch milliseconds."},"targetType":{"type":"string","enum":["email_sequence"],"description":"Record type."},"targetId":{"type":"string","description":"New sequence id."},"created":{"type":"boolean","description":"Always true; the sequence is created PAUSED."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","id","name","status","steps","recipients","pending","replied","fromAddr","stopOnReply","stats","targetType","targetId","created"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/outreach/sequences/start":{"post":{"operationId":"start_email_sequence","summary":"Start (activate) a paused outreach sequence so the platform cron begins sending it","description":"Start (activate) a paused outreach sequence so the platform cron begins sending it. PREVIEW FIRST: called without confirm it changes nothing and reports the pending recipient count, the step cadence, the sending mailbox and every mailbox's warm-up budget. Only after confirm does the sequence switch to running — first sends go out within ~10 minutes, throttled by the sequence daily cap and per-mailbox warm-up caps.\n\nRequired scope: `messages.send`. Risk level: `high`.","tags":["messages"],"security":[{"bearerAuth":["messages.send"]}],"parameters":[{"name":"id","in":"query","required":true,"description":"Sequence id from list_email_sequences or create_email_sequence.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["email_sequence"],"description":"Record type."},"targetId":{"type":"string","description":"Sequence id."},"summary":{"type":"string","description":"Preview only: what starting will do (pending count, cadence, mailbox, caps)."},"sequence":{"type":"object","properties":{"id":{"type":"string","description":"Sequence id."},"name":{"type":"string","description":"Sequence name."},"status":{"type":"string","description":"Sequence state, e.g. \"running\" or \"paused\"."},"steps":{"type":"array","items":{"type":"object","properties":{"n":{"type":"integer","description":"1-based step number."},"type":{"type":"string","description":"Step channel: email, sms, whatsapp or task."},"subject":{"type":"string","description":"Email subject (\"\" for non-email steps)."},"delayDays":{"type":"number","description":"Days after the previous step."}},"additionalProperties":true,"required":["n","type","subject","delayDays"]},"description":"Cadence steps in order."},"recipients":{"type":"integer","description":"Enrolled recipients."},"pending":{"type":"integer","description":"Recipients not done and not replied."},"replied":{"type":"integer","description":"Recipients who replied."},"fromAddr":{"type":"string","description":"Sending mailbox, \"__rotate__\", or \"(default mailbox)\"."},"dailyCap":{"type":"number","description":"Max sequence emails per day."},"stopOnReply":{"type":"boolean","description":"Cadence stops for a recipient who replies."},"stats":{"type":"object","additionalProperties":true,"description":"Cumulative counters, e.g. { sent, replies, opens }."},"createdAt":{"type":"number","description":"Creation time, epoch milliseconds."}},"additionalProperties":true,"required":["id","name","status","steps","recipients","pending","replied","fromAddr","stopOnReply","stats"],"description":"Sequence summary (same shape as list_email_sequences rows)."},"mailboxes":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string","description":"Mailbox address."},"sentToday":{"type":"integer","description":"Sends counted against the mailbox today."},"dailyCap":{"type":["number","null"],"description":"Warm-up cap for today; null = no cap."}},"additionalProperties":true,"required":["address","sentToday","dailyCap"]},"description":"Every connected mailbox with its warm-up usage today."},"started":{"type":"boolean","description":"True when the sequence switched to running; false if it already was."},"status":{"type":"string","description":"Sequence status after the call, e.g. \"running\"."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/outreach/sequences/{id}":{"get":{"operationId":"get_email_sequence","summary":"Full detail of ONE outreach email sequence: settings, steps, the exclusive recipient breakdown (notStarted / due / awaiting / delayed / completed / replied / stopped / bounced / unsubscribed — with definitions of every counter), per-recipient state (stage, next send time, thread, reply / auto-reply / bounce / delay evidence, stop reason, review flags) and the scheduler view (last run, why it sent or did not, per-mailbox daily quota used vs cap)","description":"Full detail of ONE outreach email sequence: settings, steps, the exclusive recipient breakdown (notStarted / due / awaiting / delayed / completed / replied / stopped / bounced / unsubscribed — with definitions of every counter), per-recipient state (stage, next send time, thread, reply / auto-reply / bounce / delay evidence, stop reason, review flags) and the scheduler view (last run, why it sent or did not, per-mailbox daily quota used vs cap). Filter recipients with bucket and query; paginated.\n\nRequired scope: `campaigns.read`. Risk level: `read`.","tags":["campaigns"],"security":[{"bearerAuth":["campaigns.read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Sequence id from list_email_sequences.","schema":{"type":"string","maxLength":60}},{"name":"bucket","in":"query","required":false,"description":"Only recipients in this bucket.","schema":{"type":"string","enum":["notStarted","due","awaiting","delayed","completed","replied","stopped","bounced","unsubscribed","review","autoreplied"]}},{"name":"query","in":"query","required":false,"description":"Substring of email / name / phone.","schema":{"type":"string","maxLength":120}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"sequence":{"type":"object","properties":{"id":{"type":"string","description":"Sequence id."},"name":{"type":"string","description":"Sequence name."},"status":{"type":"string","description":"running / paused."},"steps":{"type":"array","items":{"type":"object","properties":{"n":{"type":"integer","description":"1-based step number."},"type":{"type":"string","description":"email, sms, whatsapp or task."},"subject":{"type":"string","description":"Email subject."},"delayDays":{"type":"number","description":"Days after the previous step."},"delayHours":{"type":"number","description":"Extra hours after the previous step."},"skipIf":{"type":"string","description":"none, replied or opened."}},"additionalProperties":true,"required":["n","type","delayDays","delayHours","skipIf"]},"description":"Cadence steps."},"fromAddr":{"type":"string","description":"Sending mailbox, \"__rotate__\", or \"\" for the default."},"dailyCap":{"type":"number","description":"Max sequence emails per day."},"stopOnReply":{"type":"boolean","description":"Cadence stops for a recipient who replies."},"stats":{"type":"object","additionalProperties":true,"description":"Cumulative counters { sent, replies, opens, … }."},"createdAt":{"type":"number","description":"Epoch milliseconds."},"updatedAt":{"type":"number","description":"Epoch milliseconds."}},"additionalProperties":true,"required":["id","name","status","steps"],"description":"The sequence record (without its recipient list)."},"breakdown":{"type":"object","properties":{"recipients":{"type":"integer","description":"Enrolled people."},"notStarted":{"type":"integer","description":"Nothing sent yet."},"due":{"type":"integer","description":"Next step due now, waiting for a slot."},"awaiting":{"type":"integer","description":"Next step scheduled for a future time."},"delayed":{"type":"integer","description":"Provider reported a temporary delay (4.x.x)."},"completed":{"type":"integer","description":"Every step sent, no reply."},"replied":{"type":"integer","description":"A human answered."},"stopped":{"type":"integer","description":"Cadence ended without a reply."},"bounced":{"type":"integer","description":"Permanent delivery failure."},"unsubscribed":{"type":"integer","description":"Opted out."},"autoReplied":{"type":"integer","description":"Overlay: mailbox answered automatically."},"opened":{"type":"integer","description":"Overlay: tracking pixel fired."},"review":{"type":"integer","description":"Overlay: flagged for a human decision."},"byStage":{"type":"object","additionalProperties":true,"description":"Recipient count per step reached, keyed by stage number."}},"additionalProperties":true,"required":["recipients","notStarted","due","awaiting","delayed","completed","replied","stopped","bounced","unsubscribed","autoReplied","opened","review","byStage"],"description":"Exclusive recipient buckets (they add up to recipients) plus overlay counters."},"definitions":{"type":"object","additionalProperties":true,"description":"Plain-language definition of every counter and bucket name, keyed by name."},"scheduler":{"type":"object","properties":{"mailboxes":{"type":"object","additionalProperties":true,"description":"Keyed by mailbox address: { usedToday, warmupCap (null = none), warmupEnabled, noRotate, day }."},"lastRun":{"description":"Record of the engine's last run for this user, or null."},"lastTickAnywhere":{"type":["string","null"],"description":"ISO 8601 time of the last cron tick for any workspace, or null."},"userActive":{"type":"boolean","description":"This user is in the engine's active set."},"userLocked":{"type":"boolean","description":"A run for this user is in progress."},"cadence":{"type":"string","description":"How the engine schedules sends (interval, caps, day boundary)."}},"additionalProperties":true,"required":["mailboxes","lastRun","lastTickAnywhere","userActive","userLocked","cadence"],"description":"Engine state and per-mailbox quota for this sequence's mailboxes."},"recipients":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","description":"Recipient email."},"name":{"type":"string","description":"Recipient name."},"phone":{"type":"string","description":"Phone, or \"\"."},"leadId":{"type":"string","description":"Linked lead id, or \"\"."},"stage":{"type":"integer","description":"Steps sent so far."},"bucket":{"type":"string","enum":["notStarted","due","awaiting","delayed","completed","replied","stopped","bounced","unsubscribed"],"description":"Exclusive state bucket."},"nextAt":{"type":"number","description":"Next step time, epoch ms (0 = none)."},"firstSentAt":{"type":"number","description":"Epoch ms, 0 = never."},"lastSentAt":{"type":"number","description":"Epoch ms, 0 = never."},"sentFrom":{"type":"string","description":"Mailbox that sent to this recipient."},"threadId":{"type":"string","description":"Provider thread id."},"done":{"type":"boolean","description":"Cadence finished."},"doneAt":{"type":"number","description":"Epoch ms, 0 = not done."},"replied":{"type":"boolean","description":"A human replied."},"repliedAt":{"type":"number","description":"Epoch ms, 0 = none."},"replyFrom":{"type":"string","description":"Address the reply came from."},"replyMatch":{"type":"string","description":"How the reply was matched (thread, sender, domain, manual)."},"sentiment":{"type":["string","null"],"description":"AI-classified reply sentiment, or null."},"autoReplyAt":{"type":"number","description":"Epoch ms of an auto-reply, 0 = none."},"autoReplyFrom":{"type":"string","description":"Auto-reply sender."},"autoReplySubject":{"type":"string","description":"Auto-reply subject."},"bounced":{"type":"boolean","description":"Permanent delivery failure."},"bounceStatus":{"type":"string","description":"DSN status code, e.g. 5.1.1."},"bounceDiag":{"type":"string","description":"Provider diagnostic text."},"dsnDelayedAt":{"type":"number","description":"Epoch ms of a temporary delay, 0 = none."},"dsnStatus":{"type":"string","description":"Delay DSN status code."},"dsnResolved":{"type":"string","description":"How the delay resolved, or \"\"."},"unsub":{"type":"boolean","description":"Unsubscribed."},"opened":{"type":"boolean","description":"Tracking pixel fired."},"stopReason":{"type":"string","description":"Why the cadence stopped, or \"\"."},"stoppedAt":{"type":"number","description":"Epoch ms, 0 = none."},"stoppedBy":{"type":"string","description":"Who/what stopped it."},"review":{"type":"string","description":"Note for a human to act on, or \"\"."},"holdReason":{"type":"string","description":"Why the engine is holding this recipient, or \"\"."}},"additionalProperties":true,"required":["email","name","phone","leadId","stage","bucket","nextAt","firstSentAt","lastSentAt","sentFrom","threadId","done","doneAt","replied","repliedAt","replyFrom","replyMatch","sentiment","autoReplyAt","autoReplyFrom","autoReplySubject","bounced","bounceStatus","bounceDiag","dsnDelayedAt","dsnStatus","dsnResolved","unsub","opened","stopReason","stoppedAt","stoppedBy","review","holdReason"]},"description":"Per-recipient state (one page, after bucket/query filters)."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number."},"pageSize":{"type":"integer","description":"Items per page."},"total":{"type":"integer","description":"Total items across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the list."}},"additionalProperties":true,"required":["ok","requestId","sequence","breakdown","definitions","scheduler","recipients","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/outreach/sequences/{id}/delivery":{"get":{"operationId":"get_email_sequence_delivery","summary":"Delivery outcomes of ONE sequence, separated the way the engine separates them: permanent failures (5","description":"Delivery outcomes of ONE sequence, separated the way the engine separates them: permanent failures (5.x.x bounces — suppressed), temporary delays (4.x.x — provider still retrying, NOT bounces), auto-replies (out-of-office / mailbox closing — never counted as replies), human replies (with how each was matched: same thread, sender address, or company domain + quoted subject), manual stops, unsubscribes, and everything flagged for human review.\n\nRequired scope: `campaigns.read`. Risk level: `read`.","tags":["campaigns"],"security":[{"bearerAuth":["campaigns.read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Sequence id from list_email_sequences.","schema":{"type":"string","maxLength":60}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"sequence":{"type":"object","properties":{"id":{"type":"string","description":"Sequence id."},"name":{"type":"string","description":"Sequence name."},"status":{"type":"string","description":"running / paused."},"fromAddr":{"type":"string","description":"Sending mailbox, \"__rotate__\", or \"\"."},"stats":{"type":"object","additionalProperties":true,"description":"Cumulative counters { sent, replies, opens, … }."}},"additionalProperties":true,"required":["id","name","status","fromAddr","stats"],"description":"Sequence header."},"breakdown":{"type":"object","properties":{"recipients":{"type":"integer","description":"Enrolled people."},"notStarted":{"type":"integer","description":"Nothing sent yet."},"due":{"type":"integer","description":"Next step due now, waiting for a slot."},"awaiting":{"type":"integer","description":"Next step scheduled for a future time."},"delayed":{"type":"integer","description":"Provider reported a temporary delay (4.x.x)."},"completed":{"type":"integer","description":"Every step sent, no reply."},"replied":{"type":"integer","description":"A human answered."},"stopped":{"type":"integer","description":"Cadence ended without a reply."},"bounced":{"type":"integer","description":"Permanent delivery failure."},"unsubscribed":{"type":"integer","description":"Opted out."},"autoReplied":{"type":"integer","description":"Overlay: mailbox answered automatically."},"opened":{"type":"integer","description":"Overlay: tracking pixel fired."},"review":{"type":"integer","description":"Overlay: flagged for a human decision."},"byStage":{"type":"object","additionalProperties":true,"description":"Recipient count per step reached, keyed by stage number."}},"additionalProperties":true,"required":["recipients","notStarted","due","awaiting","delayed","completed","replied","stopped","bounced","unsubscribed","autoReplied","opened","review","byStage"],"description":"Exclusive recipient buckets (they add up to recipients) plus overlay counters."},"definitions":{"type":"object","additionalProperties":true,"description":"Plain-language definition of every counter and bucket name, keyed by name."},"permanentFailures":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","description":"Recipient email."},"name":{"type":"string","description":"Recipient name."},"status":{"type":"string","description":"DSN status code."},"diagnostic":{"type":"string","description":"Provider diagnostic text."},"at":{"type":["string","null"],"description":"ISO 8601, or null."},"suppressed":{"type":"boolean","description":"Always true."}},"additionalProperties":true,"required":["email","name","status","diagnostic","at","suppressed"]},"description":"5.x.x bounces — suppressed workspace-wide."},"temporaryDelays":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","description":"Recipient email."},"name":{"type":"string","description":"Recipient name."},"status":{"type":"string","description":"DSN status code."},"at":{"type":["string","null"],"description":"ISO 8601, or null."},"resolved":{"type":"string","description":"Resolution, or \"pending — provider still retrying\"."},"note":{"type":"string","description":"Explanation that nothing is re-sent meanwhile."}},"additionalProperties":true,"required":["email","name","status","at","resolved","note"]},"description":"4.x.x delays the provider is still retrying — NOT bounces."},"autoReplies":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","description":"Recipient email."},"name":{"type":"string","description":"Recipient name."},"from":{"type":"string","description":"Auto-reply sender."},"subject":{"type":"string","description":"Auto-reply subject."},"at":{"type":["string","null"],"description":"ISO 8601, or null."},"cadence":{"type":"string","description":"What happened to the cadence: stop reason, \"ended\" or \"held\"."},"review":{"type":"string","description":"Note for a human, or \"\"."}},"additionalProperties":true,"required":["email","name","from","subject","at","cadence","review"]},"description":"Out-of-office / mailbox-closing auto-replies (never counted as replies)."},"humanReplies":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","description":"Recipient email."},"name":{"type":"string","description":"Recipient name."},"from":{"type":"string","description":"Address the reply came from."},"at":{"type":["string","null"],"description":"ISO 8601, or null."},"matchedBy":{"type":"string","description":"How the reply was matched (thread, sender, domain, manual)."},"sentiment":{"type":["string","null"],"description":"AI-classified sentiment, or null."},"cadence":{"type":"string","enum":["stopped"],"description":"Always \"stopped\"."}},"additionalProperties":true,"required":["email","name","from","at","matchedBy","sentiment","cadence"]},"description":"Verified human replies."},"stopped":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","description":"Recipient email."},"name":{"type":"string","description":"Recipient name."},"reason":{"type":"string","description":"Stop reason."},"at":{"type":["string","null"],"description":"ISO 8601, or null."},"by":{"type":"string","description":"Who stopped it (\"system\" when unknown)."},"review":{"type":"string","description":"Note for a human, or \"\"."}},"additionalProperties":true,"required":["email","name","reason","at","by","review"]},"description":"Cadences ended by a person/tool without a reply or bounce."},"needsReview":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","description":"Recipient email."},"name":{"type":"string","description":"Recipient name."},"bucket":{"type":"string","description":"Current state bucket."},"review":{"type":"string","description":"What to review."}},"additionalProperties":true,"required":["email","name","bucket","review"]},"description":"Recipients flagged for a human decision."},"unsubscribed":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","description":"Recipient email."},"name":{"type":"string","description":"Recipient name."}},"additionalProperties":true,"required":["email","name"]},"description":"Recipients who opted out."}},"additionalProperties":true,"required":["ok","requestId","sequence","breakdown","definitions","permanentFailures","temporaryDelays","autoReplies","humanReplies","stopped","needsReview","unsubscribed"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/outreach/scheduler":{"get":{"operationId":"get_outreach_scheduler","summary":"The sequence engine's activity for this workspace: when it last ran, what each sequence did in that run and why (cap reached, outside sending window, idle until a date, paused mid-run), every connected mailbox's sends today vs its cap (the cap is per MAILBOX and shared by all sequences sending from it — two sequences at 20/day on one mailbox send 20 together, not 40), and whether a run is in progress","description":"The sequence engine's activity for this workspace: when it last ran, what each sequence did in that run and why (cap reached, outside sending window, idle until a date, paused mid-run), every connected mailbox's sends today vs its cap (the cap is per MAILBOX and shared by all sequences sending from it — two sequences at 20/day on one mailbox send 20 together, not 40), and whether a run is in progress. Use it before concluding the scheduler is stuck.\n\nRequired scope: `campaigns.read`. Risk level: `read`.","tags":["campaigns"],"security":[{"bearerAuth":["campaigns.read"]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"mailboxes":{"type":"object","additionalProperties":true,"description":"Keyed by mailbox address: { usedToday, warmupCap (null = none), warmupEnabled, noRotate, day }."},"lastRun":{"description":"Record of the engine's last run for this user, or null."},"lastTickAnywhere":{"type":["string","null"],"description":"ISO 8601 time of the last cron tick for any workspace, or null."},"userActive":{"type":"boolean","description":"This user is in the engine's active set."},"userLocked":{"type":"boolean","description":"A run for this user is in progress."},"cadence":{"type":"string","description":"How the engine schedules sends (interval, caps, day boundary)."}},"additionalProperties":true,"required":["ok","requestId","mailboxes","lastRun","lastTickAnywhere","userActive","userLocked","cadence"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/outreach/sequences/{id}/pause":{"post":{"operationId":"pause_email_sequence","summary":"Pause a running outreach email sequence","description":"Pause a running outreach email sequence. Safe, instant and idempotent: the engine checks a live status flag before every send, so even a run already in progress stops before its next email; recipients keep their place. Resuming is a separate, confirmed action (start_email_sequence). Never deletes anything.\n\nRequired scope: `campaigns.write`. Risk level: `write`.","tags":["campaigns"],"security":[{"bearerAuth":["campaigns.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Sequence id from list_email_sequences.","schema":{"type":"string","maxLength":60}},{"name":"reason","in":"query","required":false,"description":"Why (shown on the sequence).","schema":{"type":"string","maxLength":200}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["email_sequence"],"description":"Record type."},"targetId":{"type":"string","description":"Sequence id."},"status":{"type":"string","description":"Status after the call (always \"paused\" on success)."},"was":{"type":"string","description":"Status before the call."},"changed":{"type":"boolean","description":"False when it was already paused."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","status","was","changed"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/outreach/sequences/{id}/recipients/stop":{"post":{"operationId":"stop_email_sequence_recipient","summary":"Stop ONE recipient's cadence in an email sequence for good (they answered from another address, asked to be left alone, their mailbox is closing…)","description":"Stop ONE recipient's cadence in an email sequence for good (they answered from another address, asked to be left alone, their mailbox is closing…). Atomic against a run in progress (the engine re-checks a per-recipient stop set before each send) and idempotent. markReplied:true also records a human reply for the funnel — counted once, never twice. Nothing is deleted; the recipient stays visible as \"stopped\".\n\nRequired scope: `campaigns.write`. Risk level: `write`.","tags":["campaigns"],"security":[{"bearerAuth":["campaigns.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Sequence id.","schema":{"type":"string","maxLength":60}},{"name":"email","in":"query","required":true,"description":"Enrolled recipient email.","schema":{"type":"string","maxLength":160}},{"name":"reason","in":"query","required":false,"description":"Short reason, e.g. \"replied from personal address\", \"mailbox retiring\".","schema":{"type":"string","maxLength":120}},{"name":"markReplied","in":"query","required":false,"description":"Also count this as a human reply (only if one was verified).","schema":{"type":"boolean","default":false}},{"name":"repliedAt","in":"query","required":false,"description":"ISO time of the verified reply (default now).","schema":{"type":"string","maxLength":40}},{"name":"replyFrom","in":"query","required":false,"description":"Address the reply came from, if different from the recipient.","schema":{"type":"string","maxLength":160}},{"name":"review","in":"query","required":false,"description":"Note for a human to act on (e.g. replacement address to consider).","schema":{"type":"string","maxLength":300}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["email_sequence"],"description":"Record type."},"targetId":{"type":"string","description":"Sequence id."},"recipient":{"type":"object","properties":{"email":{"type":"string","description":"Recipient email."},"name":{"type":"string","description":"Recipient name."},"stage":{"type":"integer","description":"Steps sent so far."},"done":{"type":"boolean","description":"Always true after a stop."},"replied":{"type":"boolean","description":"Counted as a human reply."},"repliedAt":{"type":"number","description":"Epoch ms of the reply, when replied."},"stopReason":{"type":"string","description":"Why the cadence stopped."},"stoppedAt":{"type":"number","description":"Epoch ms."},"review":{"type":"string","description":"Note for a human, or \"\"."}},"additionalProperties":true,"required":["email","name","done","stopReason","stoppedAt","review"],"description":"The recipient after the stop."},"before":{"type":"object","properties":{"done":{"type":"boolean","description":"Was already done."},"replied":{"type":"boolean","description":"Was already counted as replied."},"stopReason":{"type":"string","description":"Previous stop reason, or \"\"."}},"additionalProperties":true,"required":["done","replied","stopReason"],"description":"State before the call (for idempotency checks)."},"changed":{"type":"boolean","description":"False when the recipient was already stopped (and not newly marked replied)."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","recipient","before","changed"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/outreach/email/send":{"post":{"operationId":"send_outreach_email","summary":"Send ONE email from a mailbox connected to this workspace (the Gmail/Outlook inboxes under Sequences → Email accounts), e","description":"Send ONE email from a mailbox connected to this workspace (the Gmail/Outlook inboxes under Sequences → Email accounts), e.g. for cold outreach from warmed-up addresses. NOT the campaign engine: use this — not send_email_campaign — whenever the mail should leave a real connected inbox. Content is either subject+body inline, or draftId of an email draft (rendered as a personal email: text only, no campaign wrapper, no unsubscribe footer). PREVIEW FIRST: called without confirm it changes nothing and reports which mailbox will send, its warm-up budget used today, and every connected mailbox's remaining budget. Sends count against the SAME per-mailbox daily warm-up cap the sequence engine uses, and a mailbox at its cap is refused — one recipient per call, so sending N emails is N previewed calls.\n\nRequired scope: `messages.send`. Risk level: `high`.","tags":["messages"],"security":[{"bearerAuth":["messages.send"]}],"parameters":[{"name":"to","in":"query","required":true,"description":"Recipient email address.","schema":{"type":"string","maxLength":160}},{"name":"subject","in":"query","required":false,"description":"Subject line. Required unless draftId is given (then defaults to the draft's subject).","schema":{"type":"string","maxLength":300}},{"name":"body","in":"query","required":false,"description":"Email body — plain text is fine (line breaks preserved); simple HTML accepted. Required unless draftId is given.","schema":{"type":"string","maxLength":20000}},{"name":"draftId","in":"query","required":false,"description":"Alternatively: an email draft id from list_message_drafts; its text content is sent as a personal email.","schema":{"type":"string","maxLength":80}},{"name":"from","in":"query","required":false,"description":"Sending mailbox address from the connected list, or \"__rotate__\" (default) to auto-pick the mailbox with the most warm-up budget left today.","schema":{"type":"string","maxLength":160}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["outreach_email"],"description":"Record type."},"targetId":{"type":"string","description":"Recipient email address."},"summary":{"type":"string","description":"Preview only: what would be sent, from which mailbox, and its budget; starts with BLOCKED when the mailbox has no budget left."},"fromAddress":{"type":"string","description":"Sending mailbox (auto-picked when from was omitted or \"__rotate__\")."},"sentToday":{"type":"integer","description":"Preview only: sends counted against that mailbox today."},"dailyCap":{"type":["number","null"],"description":"Preview only: warm-up cap for today; null = no cap."},"mailboxes":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string","description":"Mailbox address."},"sentToday":{"type":"integer","description":"Sends counted against the mailbox today."},"dailyCap":{"type":["number","null"],"description":"Warm-up cap for today; null = no cap."}},"additionalProperties":true,"required":["address","sentToday","dailyCap"]},"description":"Every connected mailbox with its warm-up usage today."},"sent":{"type":"boolean","description":"True once the email was handed to the mailbox provider."},"messageId":{"type":"string","description":"Provider message id, or \"\"."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","fromAddress"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/campaigns/sms/send":{"post":{"operationId":"send_sms_campaign","summary":"Send an existing SMS draft to an audience","description":"Send an existing SMS draft to an audience. PREVIEW FIRST: without confirm it reports the recipient count, the total SMS segments it will cost, and who was excluded for opting out. Numbers that replied STOP are always excluded. Create the draft with create_sms_draft first.\n\nRequired scope: `messages.send`. Risk level: `high`.","tags":["messages"],"security":[{"bearerAuth":["messages.send"]}],"parameters":[{"name":"draftId","in":"query","required":true,"description":"SMS draft id from list_message_drafts.","schema":{"type":"string","maxLength":80}},{"name":"leadIds","in":"query","required":false,"description":"Exact leads to send to.","schema":{"type":"array","maxItems":500,"items":{"type":"string"}}},{"name":"status","in":"query","required":false,"description":"Send to every lead currently in this pipeline status.","schema":{"type":"string","enum":["New","Contacted","Qualified","Scheduled a Meeting","Proposal","Negotiation","Won","Lost","Unresponsive"]}},{"name":"audience","in":"query","required":false,"description":"Set to \"all_leads\" to reach every lead with a usable phone number.","schema":{"type":"string","enum":["all_leads"]}},{"name":"senderProfileId","in":"query","required":false,"description":"Verified sender profile id. Defaults to the draft's, then the first verified profile.","schema":{"type":"string","maxLength":60}},{"name":"sendAt","in":"query","required":false,"description":"ISO 8601 time to send. Defaults to about a minute from now.","schema":{"type":"string","maxLength":40}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"action":{"type":"string","enum":["send_sms_campaign"],"description":"Preview only: the action being previewed."},"targetType":{"type":"string","enum":["sms_draft","sms_campaign"],"description":"sms_draft on preview, sms_campaign once queued."},"targetId":{"type":"string","description":"Draft id on preview; campaign id once queued."},"draft":{"type":"object","properties":{"id":{"type":"string","description":"Draft id."},"name":{"type":"string","description":"Draft name."},"message":{"type":"string","description":"Message body."},"characters":{"type":"integer","description":"Body length in characters."},"segments":{"type":"integer","description":"SMS segments per message (160 chars each)."}},"additionalProperties":true,"required":["id","name","message","characters","segments"],"description":"Preview only: the draft that would be sent."},"sender":{"description":"Preview: { id, name } of the verified sender profile; after send: the sender name string."},"audience":{"type":"object","properties":{"matched":{"type":"integer","description":"Leads matched by leadIds / status / audience."},"missingAddress":{"type":"integer","description":"Matched leads with no address on this channel."},"invalidAddress":{"type":"integer","description":"Addresses that failed format validation and were dropped."},"duplicatesRemoved":{"type":"integer","description":"Duplicate addresses collapsed to one."},"suppressed":{"type":"integer","description":"Removed as unsubscribed, bounced, complained or STOP."},"willReceive":{"type":"integer","description":"Final recipient count."}},"additionalProperties":true,"required":["matched","missingAddress","invalidAddress","duplicatesRemoved","suppressed","willReceive"],"description":"Audience accounting after suppression: how many matched and how many will actually receive."},"sampleRecipients":{"type":"array","items":{"type":"string"},"description":"Preview only: up to 5 recipient phones (E.164)."},"estimatedSegmentsTotal":{"type":"integer","description":"Preview only: segments × recipients (cost basis)."},"sendAt":{"type":"string","description":"Preview only: ISO 8601 send time, or \"immediately\"."},"warnings":{"type":"array","items":{"type":"string"},"description":"Plain-language cautions to show before confirming."},"sent":{"type":"boolean","description":"True once the campaign is queued."},"campaignId":{"type":"string","description":"Queued campaign id."},"scheduledFor":{"type":"string","description":"ISO 8601 time the send is scheduled for."},"recipients":{"type":"integer","description":"Recipients queued."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","sender","audience"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/leads/bulk-update":{"post":{"operationId":"bulk_update_leads","summary":"Change the status and/or owner of many leads at once","description":"Change the status and/or owner of many leads at once. PREVIEW FIRST: without confirm it reports how many records match, how many would actually change, and a sample. Capped per call — a larger reassignment belongs in the app where the selection is visible.\n\nRequired scope: `leads.write`. Risk level: `high`.","tags":["leads"],"security":[{"bearerAuth":["leads.write"]}],"parameters":[{"name":"leadIds","in":"query","required":false,"description":"Exact leads to update.","schema":{"type":"array","maxItems":500,"items":{"type":"string"}}},{"name":"fromStatus","in":"query","required":false,"description":"Alternatively, update every lead currently in this status.","schema":{"type":"string","enum":["New","Contacted","Qualified","Scheduled a Meeting","Proposal","Negotiation","Won","Lost","Unresponsive"]}},{"name":"status","in":"query","required":false,"description":"New status to set.","schema":{"type":"string","enum":["New","Contacted","Qualified","Scheduled a Meeting","Proposal","Negotiation","Won","Lost","Unresponsive"]}},{"name":"owner","in":"query","required":false,"description":"New owner email, or \"\" to unassign.","schema":{"type":"string","maxLength":120}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"action":{"type":"string","enum":["bulk_update_leads"],"description":"Preview only: the action being previewed."},"targetType":{"type":"string","enum":["lead"],"description":"Record type."},"matched":{"type":"integer","description":"Leads selected by leadIds / fromStatus."},"willChange":{"type":"integer","description":"Preview only: leads whose status/owner would actually change."},"alreadyCorrect":{"type":"integer","description":"Preview only: leads already in the target state."},"bySource":{"type":"object","additionalProperties":true,"description":"Preview only: matched count per lead source, keyed by source."},"change":{"type":"object","properties":{"status":{"type":"string","description":"New status, when given."},"owner":{"type":"string","description":"New owner email (\"\" = unassign), when given."}},"additionalProperties":true,"description":"Preview only: the patch to apply."},"sample":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Lead id."},"name":{"description":"Lead name."},"email":{"description":"Lead email."},"status":{"description":"Current status."},"owner":{"description":"Current owner."}},"additionalProperties":true,"required":["id","name","email","status","owner"]},"description":"Preview only: up to 5 matched leads."},"warnings":{"type":"array","items":{"type":"string"},"description":"Plain-language cautions to show before confirming."},"updated":{"type":"integer","description":"Leads written."},"unchanged":{"type":"integer","description":"Leads skipped as already correct."},"failed":{"type":"integer","description":"Leads whose write failed."},"errors":{"type":"array","items":{"type":"object","properties":{"leadId":{"type":"string","description":"Lead id."},"error":{"type":"string","description":"Error message."}},"additionalProperties":true,"required":["leadId","error"]},"description":"First 5 failures."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."},"targetId":{"type":"string","description":"Id of the record the action targets."}},"additionalProperties":true,"required":["ok","requestId","targetType","matched"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/contacts/import":{"post":{"operationId":"import_contacts","summary":"Bulk-import or migrate contacts into a Leads list (e","description":"Bulk-import or migrate contacts into a Leads list (e.g. from HubSpot) with upsert semantics: an existing contact — matched by externalId, else by email within the list, else by normalised phone when the record has no email — is UPDATED, never duplicated. Each record needs an email OR a phone. A record may carry several linked tasks (`tasks[]`, or a single `task`), each keyed by its source task id (task.hubspotTaskId / task.externalId) so re-imports update the same task; due date AND time are kept exactly as written (no timezone shift); status COMPLETED marks the task done; priority low/normal/high/urgent (HubSpot LOW/MEDIUM/HIGH accepted); owner is kept even if that user is no longer active. Notes land on the contact timeline. Re-running the same import changes nothing. The result carries one row PER RECORD (externalId, HubSpot ids, lead id, task ids, created/updated/failed + the error) and a read-back verification flag — trust the rows, not the counters. PREVIEW FIRST: without confirm it reports, per record, whether it would create or update and which are invalid, writing nothing.\n\nRequired scope: `leads.write`. Risk level: `high`.","tags":["leads"],"security":[{"bearerAuth":["leads.write"]}],"parameters":[{"name":"listId","in":"query","required":true,"description":"Target Leads list name, e.g. \"FORTVISION Sales CRM\".","schema":{"type":"string","maxLength":120}},{"name":"source","in":"query","required":false,"description":"Migration source label recorded on each contact, e.g. \"HubSpot\".","schema":{"type":"string","maxLength":80}},{"name":"records","in":"query","required":true,"description":"Contact records. Each: { email or phone (one required), name, firstName, lastName, company, website, status, owner, tags, externalId, hubspotContactId, hubspotTaskId, lastContactedAt, dueDate, consent, task:{title,description,status,dueDate,assignedTo,priority,hubspotTaskId,completedAt,createdAt}, tasks:[same shape], notes:[{body,createdAt,author,source}] }. A task-only row for an EXISTING contact: { externalId (the task id), contactExternalId | contactEmail | contactPhone, task:{…} }.","schema":{"type":"array","maxItems":500,"items":{"type":"object"}}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"action":{"type":"string","enum":["import_contacts"],"description":"Preview only: the action being previewed."},"targetType":{"type":"string","enum":["contact"],"description":"Preview only: record type."},"records":{"type":"integer","description":"Preview only: records submitted."},"wouldCreate":{"type":"integer","description":"Preview only: records that would create a contact."},"wouldUpdate":{"type":"integer","description":"Preview only: records that would update an existing contact."},"invalid":{"type":"integer","description":"Preview only: records that cannot be imported."},"sample":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","description":"Normalised email, when present."},"phone":{"type":"string","description":"Phone, when present."},"exists":{"type":"boolean","description":"A matching contact already exists."},"matchedBy":{"type":"string","description":"Match key: externalId, email, phone…"},"task":{"type":"boolean","description":"Record carries at least one task."},"tasks":{"type":"integer","description":"Tasks on the record."},"notes":{"type":"integer","description":"Notes on the record."}},"additionalProperties":true,"required":["exists","task","tasks","notes"]},"description":"Preview only: up to 5 resolved records."},"errors":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","description":"Position in the submitted records array."},"externalId":{"type":"string","description":"Record externalId, or \"\"."},"email":{"type":"string","description":"Record email, or \"\"."},"phone":{"type":"string","description":"Record phone (import only)."},"error":{"type":"string","description":"Why it failed."}},"additionalProperties":true,"required":["index","externalId","email","error"]},"description":"Records rejected or failed (first 50 on preview, 100 on import)."},"results":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","description":"Position in the submitted records array."},"externalId":{"type":"string","description":"Record externalId, or \"\"."},"email":{"type":"string","description":"Record email, or \"\"."},"phone":{"type":"string","description":"Record phone, or \"\"."},"hubspotContactId":{"type":"string","description":"HubSpot contact id, or \"\"."},"hubspotTaskIds":{"type":"array","items":{"type":"string"},"description":"Task keys derived from the record."},"contactRef":{"type":"string","description":"Contact reference used to attach tasks/notes, when given."},"action":{"type":"string","enum":["create","update","invalid","created","updated","skipped","failed"],"description":"Preview: create/update/invalid. Import: created/updated/skipped/failed."},"leadId":{"type":"string","description":"Matched or written lead id."},"matchedBy":{"type":"string","description":"Match key: externalId, email, phone, phone_conflict…"},"phoneConflict":{"type":"object","additionalProperties":true,"description":"Phone matches a DIFFERENT name: { leadId, name } — created separately, not merged."},"tasks":{"description":"Preview: task count. Import: [{ externalId, id, action, done }]."},"notes":{"type":"integer","description":"Preview only: notes on the record."},"notesAdded":{"type":"integer","description":"Import only: notes written."},"attached":{"type":"boolean","description":"Import only: tasks/notes attached to an existing contact."},"verified":{"type":"boolean","description":"Import only: contact found on read-back."},"error":{"type":"string","description":"Why the record was rejected or failed."}},"additionalProperties":true,"required":["index","externalId","email","phone","hubspotContactId","hubspotTaskIds"]},"description":"One row per submitted record."},"warnings":{"type":"array","items":{"type":"string"},"description":"Plain-language cautions to show before confirming."},"dryRun":{"type":"boolean","description":"Present (true) on the underlying preview payload."},"created":{"type":"integer","description":"Import only: contacts created."},"updated":{"type":"integer","description":"Import only: contacts updated."},"skipped":{"type":"integer","description":"Import only: records skipped (not an object)."},"failed":{"type":"integer","description":"Import only: records that failed."},"tasksCreated":{"type":"integer","description":"Import only: tasks created on the board."},"tasksUpdated":{"type":"integer","description":"Import only: tasks updated on the board."},"adoptedLegacyTasks":{"type":"integer","description":"Import only: orphaned legacy tasks brought onto the board first."},"listId":{"type":"string","description":"Import only: the list written to (\"ml:\" prefixed)."},"runId":{"type":"string","description":"Import only: idempotency run id, when one was given."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."},"targetId":{"type":"string","description":"Id of the record the action targets."}},"additionalProperties":true,"required":["ok","requestId","errors","results"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/campaigns/{id}/status":{"post":{"operationId":"update_campaign_status","summary":"Pause or activate an ad campaign on Meta, Google Ads or DV360","description":"Pause or activate an ad campaign on Meta, Google Ads or DV360. PREVIEW FIRST: without confirm it reports the current state, the intended state and recent spend. The change is applied through the platform's own change pipeline, read back from the ad platform to verify, and recorded so it can be rolled back from the AI Assistant's change history.\n\nRequired scope: `campaigns.write`. Risk level: `high`.","tags":["campaigns"],"security":[{"bearerAuth":["campaigns.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Campaign id from list_campaigns.","schema":{"type":"string","maxLength":60}},{"name":"status","in":"query","required":true,"description":"Target state.","schema":{"type":"string","enum":["ACTIVE","PAUSED"]}},{"name":"platform","in":"query","required":false,"description":"Platform the id belongs to.","schema":{"type":"string","enum":["meta","google","dv360"]}},{"name":"accountId","in":"query","required":false,"description":"Ad account id, so the campaign is found without scanning every account.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"action":{"type":"string","enum":["update_campaign_status"],"description":"Preview only: the action being previewed."},"targetType":{"type":"string","enum":["campaign"],"description":"Record type."},"targetId":{"type":"string","description":"Campaign id."},"campaign":{"type":"object","properties":{"id":{"type":"string","description":"Campaign id (platform prefix stripped)."},"name":{"type":"string","description":"Campaign name."},"platform":{"type":"string","enum":["meta","google","dv360"],"description":"Ad platform."},"accountId":{"type":"string","description":"Ad account id (preview only)."},"currency":{"type":"string","description":"Account currency code (budget tool only)."}},"additionalProperties":true,"required":["id","name","platform"],"description":"The campaign being changed."},"from":{"description":"Status before: current status on preview; as recorded by the change pipeline after apply."},"to":{"description":"Status after: the intended status on preview; the read-back status after apply."},"noop":{"type":"boolean","description":"Preview only: the campaign is already in that state."},"spendLast30d":{"type":"number","description":"Preview only: spend over the campaign list's date preset, account currency."},"warnings":{"type":"array","items":{"type":"string"},"description":"Plain-language cautions to show before confirming."},"updated":{"type":"boolean","description":"True once the change was applied."},"verified":{"type":"boolean","description":"Read-back from the ad platform matched the intended status."},"changeId":{"description":"Id of the rollbackable change record."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","campaign","from","to"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/campaigns/{id}/budget":{"post":{"operationId":"update_campaign_budget","summary":"Change an ad campaign's daily budget, in the ACCOUNT CURRENCY (not cents or micros)","description":"Change an ad campaign's daily budget, in the ACCOUNT CURRENCY (not cents or micros). PREVIEW FIRST: without confirm it reports the current budget, the new one, the percentage change and recent spend, and warns if the change looks like a unit mistake. Applied, verified against the ad platform and rollbackable.\n\nRequired scope: `budgets.write`. Risk level: `high`.","tags":["budgets"],"security":[{"bearerAuth":["budgets.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Campaign id from list_campaigns.","schema":{"type":"string","maxLength":60}},{"name":"dailyBudget","in":"query","required":true,"description":"New daily budget in the account currency, e.g. 250 for ₪250/day.","schema":{"type":"number","minimum":0.01}},{"name":"platform","in":"query","required":false,"description":"Platform the id belongs to.","schema":{"type":"string","enum":["meta","google","dv360"]}},{"name":"accountId","in":"query","required":false,"description":"Ad account id.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"action":{"type":"string","enum":["update_campaign_budget"],"description":"Preview only: the action being previewed."},"targetType":{"type":"string","enum":["campaign"],"description":"Record type."},"targetId":{"type":"string","description":"Campaign id."},"campaign":{"type":"object","properties":{"id":{"type":"string","description":"Campaign id (platform prefix stripped)."},"name":{"type":"string","description":"Campaign name."},"platform":{"type":"string","enum":["meta","google","dv360"],"description":"Ad platform."},"accountId":{"type":"string","description":"Ad account id (preview only)."},"currency":{"type":"string","description":"Account currency code (budget tool only)."}},"additionalProperties":true,"required":["id","name","platform"],"description":"The campaign being changed."},"from":{"description":"Daily budget before, account currency (null when unknown on preview)."},"to":{"description":"Daily budget after: requested on preview; read back from the platform after apply."},"changePct":{"type":["number","null"],"description":"Preview only: percentage change vs the current budget; null when unknown."},"spendLast30d":{"type":"number","description":"Preview only: spend over the campaign list's date preset, account currency."},"warnings":{"type":"array","items":{"type":"string"},"description":"Plain-language cautions to show before confirming."},"updated":{"type":"boolean","description":"True once the change was applied."},"verified":{"type":"boolean","description":"Read-back from the ad platform matched the new budget."},"changeId":{"description":"Id of the rollbackable change record."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","campaign","from","to"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/tasks/{id}/delete":{"post":{"operationId":"delete_task","summary":"Permanently delete a CRM task","description":"Permanently delete a CRM task. PREVIEW FIRST: without confirm it shows the task that would be destroyed. There is no undo and no trash — prefer complete_task unless the task should never have existed.\n\nRequired scope: `records.delete`. Risk level: `high`.","tags":["records"],"security":[{"bearerAuth":["records.delete"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Task id from list_tasks.","schema":{"type":"string","maxLength":80}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"action":{"type":"string","enum":["delete_task"],"description":"Preview only: the action being previewed."},"targetType":{"type":"string","enum":["task"],"description":"Record type."},"targetId":{"type":"string","description":"Task id."},"task":{"type":"object","properties":{"id":{"type":"string","description":"Task id."},"title":{"type":"string","description":"Task title."},"done":{"type":"boolean","description":"Completed."},"priority":{"type":"string","description":"Normalised priority (\"\" when none)."},"priorityLabel":{"type":"string","description":"Priority as stored."},"owner":{"type":"string","description":"Assignee email."},"dueAt":{"type":"string","description":"Due time, ISO 8601, or \"\"."},"relatedTo":{"type":["object","null"],"properties":{"type":{"type":"string","description":"Entity type, e.g. lead."},"id":{"type":"string","description":"Entity id."}},"additionalProperties":true,"required":["type","id"],"description":"Linked record, or null."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."},"updatedAt":{"type":"string","description":"ISO 8601 or \"\"."}},"additionalProperties":true,"required":["id","title","done","priority","priorityLabel","owner","dueAt","relatedTo","createdAt","updatedAt"],"description":"The task record."},"warnings":{"type":"array","items":{"type":"string"},"description":"Plain-language cautions to show before confirming."},"deleted":{"type":"boolean","description":"True once the task is gone."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","task"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/campaign-drafts":{"get":{"operationId":"list_campaign_drafts","summary":"Campaign drafts saved in the Meta, Google Ads and DV360 publish wizards but not yet published: name, type, ad account, and how many ad groups / ad sets / creatives each has","description":"Campaign drafts saved in the Meta, Google Ads and DV360 publish wizards but not yet published: name, type, ad account, and how many ad groups / ad sets / creatives each has. These are what publish_campaign_draft can put live.\n\nRequired scope: `campaigns.read`. Risk level: `read`.","tags":["campaigns"],"security":[{"bearerAuth":["campaigns.read"]}],"parameters":[{"name":"platform","in":"query","required":false,"description":"Restrict to one platform.","schema":{"type":"string","enum":["meta","google","dv360"]}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"drafts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Draft id."},"platform":{"type":"string","enum":["meta","google","dv360"],"description":"Wizard the draft belongs to."},"name":{"type":"string","description":"Draft name."},"type":{"type":"string","description":"Campaign type."},"adAccountId":{"type":"string","description":"Ad account / customer / advertiser id (\"act_\" stripped)."},"adGroups":{"type":"integer","description":"Ad group count, when known."},"adSets":{"type":"integer","description":"Ad set count, when known."},"creatives":{"type":"integer","description":"Creative count, when known."},"updatedAt":{"type":"string","description":"ISO 8601, or \"\"."}},"additionalProperties":true,"required":["id","platform","name","type","adAccountId","updatedAt"]},"description":"Unpublished wizard drafts, newest first."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number."},"pageSize":{"type":"integer","description":"Items per page."},"total":{"type":"integer","description":"Total items across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the list."},"notes":{"type":"array","items":{"type":"string"},"description":"Platforms whose draft list could not be read, with the reason."}},"additionalProperties":true,"required":["ok","requestId","drafts","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/campaign-drafts/{draftId}/publish":{"post":{"operationId":"publish_campaign_draft","summary":"Publish a saved campaign draft to the ad platform, creating a real campaign","description":"Publish a saved campaign draft to the ad platform, creating a real campaign. PREVIEW FIRST: without confirm it summarises the campaign in plain language — name, type, budget, countries, how many ad sets and creatives — and warns about anything missing. Meta campaigns are created PAUSED so they can be reviewed before spending. This tool cannot invent a campaign: build or edit the draft in the publish wizard first, then publish it here.\n\nRequired scope: `campaigns.write`. Risk level: `high`.","tags":["campaigns"],"security":[{"bearerAuth":["campaigns.write"]}],"parameters":[{"name":"platform","in":"query","required":true,"description":"Which wizard the draft belongs to.","schema":{"type":"string","enum":["meta","google","dv360"]}},{"name":"draftId","in":"path","required":true,"description":"Draft id from list_campaign_drafts.","schema":{"type":"string","maxLength":80}},{"name":"accountId","in":"query","required":false,"description":"Ad account / customer / advertiser id, if the draft does not carry one.","schema":{"type":"string","maxLength":60}},{"name":"pageId","in":"query","required":false,"description":"Meta only: the Facebook Page ads run from, if the draft does not carry one.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"action":{"type":"string","enum":["publish_campaign_draft"],"description":"Preview only: the action being previewed."},"targetType":{"type":"string","enum":["campaign_draft","campaign"],"description":"campaign_draft on preview, campaign once published."},"targetId":{"type":"string","description":"Draft id on preview; new campaign id once published (\"\" if the platform returned none)."},"platform":{"type":"string","enum":["meta","google","dv360"],"description":"Ad platform."},"adAccountId":{"type":"string","description":"Preview only: ad account the campaign will be created in."},"campaign":{"type":"object","properties":{"name":{"type":"string","description":"Campaign name."},"type":{"type":"string","description":"Campaign type / objective."},"dailyBudget":{"type":["number","null"],"description":"Daily budget in account currency, or null."},"lifetimeBudget":{"type":["number","null"],"description":"Lifetime budget in account currency, or null."},"countries":{"type":"array","items":{"type":"string"},"description":"Targeted countries (first 20), when set."},"adGroups":{"type":"integer","description":"Ad group count (Google)."},"adSets":{"type":"integer","description":"Ad set count (Meta)."},"creatives":{"type":"integer","description":"Creative count."},"lineItems":{"type":"integer","description":"Line item count (DV360)."},"adGroupNames":{"type":"array","items":{"type":"string"},"description":"First 5 ad group names (Google only)."},"adSetNames":{"type":"array","items":{"type":"string"},"description":"First 5 ad set names (Meta only)."}},"additionalProperties":true,"required":["name","type","dailyBudget","lifetimeBudget"],"description":"Plain-language summary of the draft's campaign plan."},"warnings":{"description":"Preview: string cautions. After publish: the platform's own warnings (e.g. image warnings), if any."},"published":{"type":"boolean","description":"True once the campaign was created."},"campaignId":{"type":"string","description":"New campaign id on the platform (\"\" if not returned)."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","platform","campaign"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/whatsapp/templates":{"get":{"operationId":"list_whatsapp_templates","summary":"WhatsApp message templates on this workspace's Business account, with their approval status, language, category, body text and how many variables each takes — plus the sender numbers available","description":"WhatsApp message templates on this workspace's Business account, with their approval status, language, category, body text and how many variables each takes — plus the sender numbers available. Outside a 24-hour service window Meta only delivers approved templates, so start here before sending.\n\nRequired scope: `conversations.read`. Risk level: `read`.","tags":["conversations"],"security":[{"bearerAuth":["conversations.read"]}],"parameters":[{"name":"approvedOnly","in":"query","required":false,"description":"Only templates Meta has approved. Default true.","schema":{"type":"boolean","default":true}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"templates":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Template id."},"name":{"type":"string","description":"Template name."},"status":{"type":"string","description":"Meta review status, e.g. APPROVED."},"language":{"type":"string","description":"Language code, e.g. he, en_US."},"category":{"type":"string","description":"MARKETING / UTILITY / AUTHENTICATION."},"variables":{"type":"integer","description":"Number of {{n}} placeholders."},"body":{"type":"string","description":"Template body text."}},"additionalProperties":true,"required":["id","name","status","language","category","variables","body"]},"description":"WhatsApp message templates (approved only unless approvedOnly:false)."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number."},"pageSize":{"type":"integer","description":"Items per page."},"total":{"type":"integer","description":"Total items across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the list."},"senders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Phone number id."},"phone":{"type":"string","description":"Display phone number."},"name":{"type":"string","description":"Business name."}},"additionalProperties":true,"required":["id","phone","name"]},"description":"Connected WhatsApp Business phone numbers."}},"additionalProperties":true,"required":["ok","requestId","templates","pagination","senders"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/whatsapp/send":{"post":{"operationId":"send_whatsapp_message","summary":"Send an approved WhatsApp template to an audience","description":"Send an approved WhatsApp template to an audience. PREVIEW FIRST: without confirm it shows the template body that will actually arrive, the recipient count, and who was excluded for opting out. Numbers that opted out are always removed. Capped at 500 recipients per call. Unapproved templates are refused — Meta would not deliver them.\n\nRequired scope: `messages.send`. Risk level: `high`.","tags":["messages"],"security":[{"bearerAuth":["messages.send"]}],"parameters":[{"name":"templateName","in":"query","required":true,"description":"Template name or id from list_whatsapp_templates.","schema":{"type":"string","maxLength":120}},{"name":"templateVariables","in":"query","required":false,"description":"Values for the template placeholders, in order.","schema":{"type":"array","maxItems":10,"items":{"type":"string"}}},{"name":"leadIds","in":"query","required":false,"description":"Exact leads to message.","schema":{"type":"array","maxItems":500,"items":{"type":"string"}}},{"name":"status","in":"query","required":false,"description":"Message every lead currently in this pipeline status.","schema":{"type":"string","enum":["New","Contacted","Qualified","Scheduled a Meeting","Proposal","Negotiation","Won","Lost","Unresponsive"]}},{"name":"audience","in":"query","required":false,"description":"Set to \"all_leads\" to reach every lead with a usable phone number.","schema":{"type":"string","enum":["all_leads"]}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"action":{"type":"string","enum":["send_whatsapp_message"],"description":"Preview only: the action being previewed."},"targetType":{"type":"string","enum":["whatsapp_template","whatsapp_send"],"description":"whatsapp_template on preview, whatsapp_send once queued."},"targetId":{"type":"string","description":"Template id on preview; send campaign id (or template id) once queued."},"template":{"description":"Preview: { id, name, language, category, body, variables }; after send: the template name string."},"audience":{"type":"object","properties":{"matched":{"type":"integer","description":"Leads matched by leadIds / status / audience."},"missingAddress":{"type":"integer","description":"Matched leads with no address on this channel."},"invalidAddress":{"type":"integer","description":"Addresses that failed format validation and were dropped."},"duplicatesRemoved":{"type":"integer","description":"Duplicate addresses collapsed to one."},"suppressed":{"type":"integer","description":"Removed as unsubscribed, bounced, complained or STOP."},"willReceive":{"type":"integer","description":"Final recipient count."}},"additionalProperties":true,"required":["matched","missingAddress","invalidAddress","duplicatesRemoved","suppressed","willReceive"],"description":"Audience accounting after suppression: how many matched and how many will actually receive."},"sampleRecipients":{"type":"array","items":{"type":"string"},"description":"Preview only: up to 5 recipient phones (E.164)."},"warnings":{"type":"array","items":{"type":"string"},"description":"Plain-language cautions to show before confirming."},"sent":{"type":"boolean","description":"True once the send is queued."},"recipients":{"type":"integer","description":"Recipients queued."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId","template","audience"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/webhooks/events":{"get":{"operationId":"list_webhook_events","summary":"The event types a webhook subscription can listen for, with what each one means","description":"The event types a webhook subscription can listen for, with what each one means. Call this before creating a subscription so you use real event names.\n\nRequired scope: `admin.integrations`. Risk level: `read`.","tags":["admin"],"security":[{"bearerAuth":["admin.integrations"]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"events":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","enum":["lead.created","lead.updated","lead.status_changed","task.created","task.completed","task.overdue","deal.created","deal.updated","deal.stage_changed","deal.won","campaign.status_changed","campaign.budget_changed","message.sent","customer.updated","conversation.created","conversation.assigned","conversation.closed","csat.received"],"description":"Event type name to pass in create_webhook.events."},"description":{"type":"string","description":"What triggers the event."}},"additionalProperties":true,"required":["name","description"],"description":"One event type."},"description":"Every event type a subscription can listen for."},"signatureHeader":{"type":"string","description":"How the X-Fortvision-Signature header is built (HMAC-SHA256 over `${t}.${rawBody}`)."},"idempotencyHeader":{"type":"string","description":"Note that X-Fortvision-Event-Id is stable across retries."}},"additionalProperties":true,"required":["ok","requestId","events","signatureHeader","idempotencyHeader"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/webhooks":{"get":{"operationId":"list_webhooks","summary":"The webhook endpoints registered for this workspace, with their events, whether they are active, their last delivery result and how many consecutive failures they have","description":"The webhook endpoints registered for this workspace, with their events, whether they are active, their last delivery result and how many consecutive failures they have. Secrets are never returned — only a hint of the first and last characters.\n\nRequired scope: `admin.integrations`. Risk level: `read`.","tags":["admin"],"security":[{"bearerAuth":["admin.integrations"]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"webhooks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Subscription id (wh_…)."},"url":{"type":"string","description":"https endpoint that receives deliveries."},"events":{"type":"array","items":{"type":"string","description":"Event type, e.g. lead.created."},"description":"Subscribed event type names."},"description":{"type":"string","description":"Caller-supplied description, \"\" when none."},"active":{"type":"boolean","description":"False when disabled by the caller or auto-disabled after repeated failures."},"createdAt":{"type":"number","description":"Creation time, Unix epoch milliseconds."},"createdBy":{"type":"string","description":"Email of the user whose token created it (lowercase), \"\" when unknown."},"lastDeliveryAt":{"type":"number","description":"Last delivery attempt, Unix epoch ms; 0 when never delivered."},"lastStatus":{"description":"HTTP status of the last attempt, or an error string on failure; null when never delivered."},"consecutiveFailures":{"type":"integer","description":"Failed attempts in a row; 20 auto-disables the endpoint."},"disabledAt":{"type":"number","description":"Auto-disable time, Unix epoch ms; 0 when not disabled."},"disabledReason":{"type":"string","description":"Why it was auto-disabled, \"\" when not."},"secretRotatedAt":{"type":"number","description":"Last secret rotation, Unix epoch ms; 0 when never rotated."},"secretHint":{"type":"string","description":"First 11 and last 4 characters of the signing secret, never the secret itself."}},"additionalProperties":true,"required":["id","url","events","description","active","createdAt","createdBy","lastDeliveryAt","lastStatus","consecutiveFailures","disabledAt","disabledReason","secretRotatedAt","secretHint"],"description":"One subscription, secret stripped."},"description":"Subscriptions in this workspace, newest first, secrets stripped."}},"additionalProperties":true,"required":["ok","requestId","webhooks"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"create_webhook","summary":"Register an https endpoint to receive signed event deliveries","description":"Register an https endpoint to receive signed event deliveries. The signing secret is returned ONCE — store it, because it is the only thing that proves a delivery came from FORTVISION. Verify each request by recomputing HMAC-SHA256 over `${timestamp}.${rawBody}` using the RAW body, and reject deliveries whose timestamp is more than a few minutes old.\n\nRequired scope: `admin.integrations`. Risk level: `write`.","tags":["admin"],"security":[{"bearerAuth":["admin.integrations"]}],"parameters":[{"name":"url","in":"query","required":true,"description":"https endpoint to POST to. Must be a public host.","schema":{"type":"string","maxLength":500}},{"name":"events","in":"query","required":true,"description":"Event types to subscribe to — see list_webhook_events.","schema":{"type":"array","maxItems":20,"items":{"type":"string"}}},{"name":"description","in":"query","required":false,"description":"What this endpoint is for.","schema":{"type":"string","maxLength":200}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"subscription":{"type":"object","properties":{"id":{"type":"string","description":"Subscription id (wh_…)."},"url":{"type":"string","description":"https endpoint that receives deliveries."},"events":{"type":"array","items":{"type":"string","description":"Event type, e.g. lead.created."},"description":"Subscribed event type names."},"description":{"type":"string","description":"Caller-supplied description, \"\" when none."},"active":{"type":"boolean","description":"False when disabled by the caller or auto-disabled after repeated failures."},"createdAt":{"type":"number","description":"Creation time, Unix epoch milliseconds."},"createdBy":{"type":"string","description":"Email of the user whose token created it (lowercase), \"\" when unknown."},"lastDeliveryAt":{"type":"number","description":"Last delivery attempt, Unix epoch ms; 0 when never delivered."},"lastStatus":{"description":"HTTP status of the last attempt, or an error string on failure; null when never delivered."},"consecutiveFailures":{"type":"integer","description":"Failed attempts in a row; 20 auto-disables the endpoint."},"disabledAt":{"type":"number","description":"Auto-disable time, Unix epoch ms; 0 when not disabled."},"disabledReason":{"type":"string","description":"Why it was auto-disabled, \"\" when not."},"secretRotatedAt":{"type":"number","description":"Last secret rotation, Unix epoch ms; 0 when never rotated."},"secretHint":{"type":"string","description":"First 11 and last 4 characters of the signing secret, never the secret itself."}},"additionalProperties":true,"required":["id","url","events","description","active","createdAt","createdBy","lastDeliveryAt","lastStatus","consecutiveFailures","disabledAt","disabledReason","secretRotatedAt","secretHint"],"description":"The subscription without its secret."},"secret":{"type":"string","description":"Signing secret (whsec_…), returned ONCE — store it."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","subscription","secret"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/webhooks/{id}/update":{"post":{"operationId":"update_webhook","summary":"Change a webhook endpoint's URL, event list or description, or re-enable one that was auto-disabled after repeated failures","description":"Change a webhook endpoint's URL, event list or description, or re-enable one that was auto-disabled after repeated failures.\n\nRequired scope: `admin.integrations`. Risk level: `write`.","tags":["admin"],"security":[{"bearerAuth":["admin.integrations"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Subscription id from list_webhooks.","schema":{"type":"string","maxLength":60}},{"name":"url","in":"query","required":false,"description":"New https endpoint.","schema":{"type":"string","maxLength":500}},{"name":"events","in":"query","required":false,"description":"Replacement event list.","schema":{"type":"array","maxItems":20,"items":{"type":"string"}}},{"name":"description","in":"query","required":false,"description":"New description.","schema":{"type":"string","maxLength":200}},{"name":"active","in":"query","required":false,"description":"Enable or disable deliveries. Enabling also clears the failure counter.","schema":{"type":"boolean"}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"subscription":{"type":"object","properties":{"id":{"type":"string","description":"Subscription id (wh_…)."},"url":{"type":"string","description":"https endpoint that receives deliveries."},"events":{"type":"array","items":{"type":"string","description":"Event type, e.g. lead.created."},"description":"Subscribed event type names."},"description":{"type":"string","description":"Caller-supplied description, \"\" when none."},"active":{"type":"boolean","description":"False when disabled by the caller or auto-disabled after repeated failures."},"createdAt":{"type":"number","description":"Creation time, Unix epoch milliseconds."},"createdBy":{"type":"string","description":"Email of the user whose token created it (lowercase), \"\" when unknown."},"lastDeliveryAt":{"type":"number","description":"Last delivery attempt, Unix epoch ms; 0 when never delivered."},"lastStatus":{"description":"HTTP status of the last attempt, or an error string on failure; null when never delivered."},"consecutiveFailures":{"type":"integer","description":"Failed attempts in a row; 20 auto-disables the endpoint."},"disabledAt":{"type":"number","description":"Auto-disable time, Unix epoch ms; 0 when not disabled."},"disabledReason":{"type":"string","description":"Why it was auto-disabled, \"\" when not."},"secretRotatedAt":{"type":"number","description":"Last secret rotation, Unix epoch ms; 0 when never rotated."},"secretHint":{"type":"string","description":"First 11 and last 4 characters of the signing secret, never the secret itself."}},"additionalProperties":true,"required":["id","url","events","description","active","createdAt","createdBy","lastDeliveryAt","lastStatus","consecutiveFailures","disabledAt","disabledReason","secretRotatedAt","secretHint"],"description":"The subscription without its secret."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","subscription"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/webhooks/{id}/rotate":{"post":{"operationId":"rotate_webhook_secret","summary":"Issue a new signing secret for an endpoint","description":"Issue a new signing secret for an endpoint. The old secret keeps signing alongside the new one for 24 hours, so you can deploy the new value without dropping deliveries in between. The new secret is returned once.\n\nRequired scope: `admin.integrations`. Risk level: `write`.","tags":["admin"],"security":[{"bearerAuth":["admin.integrations"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Subscription id from list_webhooks.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"subscription":{"type":"object","properties":{"id":{"type":"string","description":"Subscription id (wh_…)."},"url":{"type":"string","description":"https endpoint that receives deliveries."},"events":{"type":"array","items":{"type":"string","description":"Event type, e.g. lead.created."},"description":"Subscribed event type names."},"description":{"type":"string","description":"Caller-supplied description, \"\" when none."},"active":{"type":"boolean","description":"False when disabled by the caller or auto-disabled after repeated failures."},"createdAt":{"type":"number","description":"Creation time, Unix epoch milliseconds."},"createdBy":{"type":"string","description":"Email of the user whose token created it (lowercase), \"\" when unknown."},"lastDeliveryAt":{"type":"number","description":"Last delivery attempt, Unix epoch ms; 0 when never delivered."},"lastStatus":{"description":"HTTP status of the last attempt, or an error string on failure; null when never delivered."},"consecutiveFailures":{"type":"integer","description":"Failed attempts in a row; 20 auto-disables the endpoint."},"disabledAt":{"type":"number","description":"Auto-disable time, Unix epoch ms; 0 when not disabled."},"disabledReason":{"type":"string","description":"Why it was auto-disabled, \"\" when not."},"secretRotatedAt":{"type":"number","description":"Last secret rotation, Unix epoch ms; 0 when never rotated."},"secretHint":{"type":"string","description":"First 11 and last 4 characters of the signing secret, never the secret itself."}},"additionalProperties":true,"required":["id","url","events","description","active","createdAt","createdBy","lastDeliveryAt","lastStatus","consecutiveFailures","disabledAt","disabledReason","secretRotatedAt","secretHint"],"description":"The subscription without its secret."},"secret":{"type":"string","description":"New signing secret (whsec_…), returned ONCE."},"note":{"type":"string","description":"States until when (ISO 8601) the previous secret keeps signing (24 h overlap)."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","subscription","secret","note"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/webhooks/{id}/test":{"post":{"operationId":"test_webhook","summary":"Send a synthetic webhook","description":"Send a synthetic webhook.test delivery to one endpoint right now and report the HTTP status it returned. Use it to prove signature verification works before relying on real events.\n\nRequired scope: `admin.integrations`. Risk level: `write`.","tags":["admin"],"security":[{"bearerAuth":["admin.integrations"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Subscription id from list_webhooks.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"delivered":{"type":"boolean","description":"True when the endpoint returned 2xx."},"httpStatus":{"type":"integer","description":"HTTP status returned; 0 on a network error or timeout."},"error":{"type":"string","description":"Network error (\"timeout\" or message), \"\" when an HTTP response arrived."},"durationMs":{"type":"number","description":"Round-trip time in milliseconds."},"hint":{"type":"string","description":"What to check when the endpoint did not accept the delivery."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","delivered","httpStatus","error","durationMs","hint"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/webhooks/deliveries":{"get":{"operationId":"list_webhook_deliveries","summary":"Recent delivery attempts for this workspace: which event, which endpoint, which attempt number, the HTTP status or error, and how long it took","description":"Recent delivery attempts for this workspace: which event, which endpoint, which attempt number, the HTTP status or error, and how long it took. Use it to debug an endpoint that is not receiving.\n\nRequired scope: `admin.integrations`. Risk level: `read`.","tags":["admin"],"security":[{"bearerAuth":["admin.integrations"]}],"parameters":[{"name":"limit","in":"query","required":false,"description":"How many attempts to return.","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"deliveries":{"type":"array","items":{"type":"object","properties":{"ts":{"type":"number","description":"Attempt time, Unix epoch milliseconds."},"deliveryId":{"type":"string","description":"Delivery id (whd_…); test deliveries are whd_test_…."},"subscriptionId":{"type":"string","description":"Subscription the attempt went to."},"eventId":{"type":"string","description":"Event id, stable across retries."},"eventType":{"type":"string","description":"Event type name (webhook.test for test deliveries)."},"attempt":{"type":"integer","description":"1-based attempt number."},"ok":{"type":"boolean","description":"True when the endpoint returned 2xx."},"status":{"type":"integer","description":"HTTP status; 0 on a network error or timeout."},"error":{"type":"string","description":"Network error (\"timeout\" or message), \"\" when an HTTP response arrived."},"durationMs":{"type":"number","description":"Round-trip time in milliseconds."}},"additionalProperties":true,"required":["ts","deliveryId","subscriptionId","eventId","eventType","attempt","ok","status","error","durationMs"],"description":"One delivery attempt."},"description":"Most recent delivery attempts first (log capped at 200)."}},"additionalProperties":true,"required":["ok","requestId","deliveries"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/webhooks/{id}/delete":{"post":{"operationId":"delete_webhook","summary":"Permanently remove a webhook endpoint","description":"Permanently remove a webhook endpoint. PREVIEW FIRST: without confirm it shows which endpoint and events would stop. Any integration relying on those deliveries stops receiving them immediately.\n\nRequired scope: `admin.integrations`. Risk level: `high`.","tags":["admin"],"security":[{"bearerAuth":["admin.integrations"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Subscription id from list_webhooks.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"action":{"type":"string","enum":["delete_webhook"],"description":"Preview only: always \"delete_webhook\"."},"targetType":{"type":"string","enum":["webhook"],"description":"Preview only: always \"webhook\"."},"targetId":{"type":"string","description":"Preview only: id of the subscription that would be removed."},"webhook":{"type":"object","properties":{"id":{"type":"string","description":"Subscription id (wh_…)."},"url":{"type":"string","description":"https endpoint that receives deliveries."},"events":{"type":"array","items":{"type":"string","description":"Event type, e.g. lead.created."},"description":"Subscribed event type names."},"description":{"type":"string","description":"Caller-supplied description, \"\" when none."},"active":{"type":"boolean","description":"False when disabled by the caller or auto-disabled after repeated failures."},"createdAt":{"type":"number","description":"Creation time, Unix epoch milliseconds."},"createdBy":{"type":"string","description":"Email of the user whose token created it (lowercase), \"\" when unknown."},"lastDeliveryAt":{"type":"number","description":"Last delivery attempt, Unix epoch ms; 0 when never delivered."},"lastStatus":{"description":"HTTP status of the last attempt, or an error string on failure; null when never delivered."},"consecutiveFailures":{"type":"integer","description":"Failed attempts in a row; 20 auto-disables the endpoint."},"disabledAt":{"type":"number","description":"Auto-disable time, Unix epoch ms; 0 when not disabled."},"disabledReason":{"type":"string","description":"Why it was auto-disabled, \"\" when not."},"secretRotatedAt":{"type":"number","description":"Last secret rotation, Unix epoch ms; 0 when never rotated."},"secretHint":{"type":"string","description":"First 11 and last 4 characters of the signing secret, never the secret itself."}},"additionalProperties":true,"required":["id","url","events","description","active","createdAt","createdBy","lastDeliveryAt","lastStatus","consecutiveFailures","disabledAt","disabledReason","secretRotatedAt","secretHint"],"description":"Preview only: the subscription that would be removed, secret stripped."},"warnings":{"type":"array","items":{"type":"string","description":"Warning text."},"description":"Preview only: what stops when it is deleted."},"deleted":{"type":"boolean","description":"Confirmed run only: always true."},"id":{"type":"string","description":"Confirmed run only: id of the removed subscription."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/senders":{"get":{"operationId":"list_linkedin_senders","summary":"The LinkedIn accounts (senders) connected to this workspace: status (available / cooling-down / disconnected), daily action limits and how much of each was used today","description":"The LinkedIn accounts (senders) connected to this workspace: status (available / cooling-down / disconnected), daily action limits and how much of each was used today. Call this before creating a sequence — senderIds come from here. Senders are connected in the app only; this API never handles LinkedIn credentials.\n\nRequired scope: `linkedin.read`. Risk level: `read`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.read"]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"live":{"type":"boolean","description":"True when the LinkedIn provider is configured (real accounts, not demo)."},"senders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Sender id (use in senderIds)."},"name":{"type":"string","description":"Display name (real LinkedIn name when resolved)."},"headline":{"type":"string","description":"LinkedIn headline."},"status":{"type":"string","description":"available | disconnected | checkpoint | restricted …"},"paused":{"type":"boolean","description":"Manually paused in the app."},"coolingUntil":{"type":"string","description":"ISO 8601 end of a rate-limit cooldown, only while cooling."},"dailyLimits":{"type":"object","properties":{"follows":{"type":"integer","description":"Max follows per day."},"messages":{"type":"integer","description":"Max messages per day."},"inmails":{"type":"integer","description":"Max InMails per day."},"invites":{"type":"integer","description":"Max connection invites per day."},"views":{"type":"integer","description":"Max profile views per day."},"likes":{"type":"integer","description":"Max post likes per day."}},"additionalProperties":true,"description":"Per-day action caps, only when configured."},"sentToday":{"type":"object","additionalProperties":true,"description":"Today's usage, metric → count (invites, messages, views, likes, inmails …)."}},"additionalProperties":true,"required":["id","name","headline","status","paused","sentToday"],"description":"One connected LinkedIn account."},"description":"Connected senders; [] for restricted users."}},"additionalProperties":true,"required":["ok","requestId","live","senders"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/lists":{"get":{"operationId":"list_linkedin_lists","summary":"Prospect lists for LinkedIn outreach: how each was built (search / post engagers / URLs / CSV), its import status and prospect count","description":"Prospect lists for LinkedIn outreach: how each was built (search / post engagers / URLs / CSV), its import status and prospect count. A sequence targets one of these lists.\n\nRequired scope: `linkedin.read`. Risk level: `read`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.read"]}],"parameters":[{"name":"query","in":"query","required":false,"description":"Substring of the list name.","schema":{"type":"string","maxLength":120}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"lists":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"List id."},"name":{"type":"string","description":"List name."},"source":{"type":"string","description":"How it was built: search | post | urls | csv."},"status":{"type":"string","description":"Import state: importing | ready."},"count":{"type":"integer","description":"Prospects in the list (grows while importing)."},"createdAt":{"type":"string","description":"ISO 8601 creation time."}},"additionalProperties":true,"required":["id","name","source","status","count","createdAt"],"description":"Prospect list."},"description":"Prospect lists, newest first."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (capped server-side)."},"total":{"type":"integer","description":"Total rows after filtering, across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page info from lib/mcp/schema.js paginate()."}},"additionalProperties":true,"required":["ok","requestId","lists","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"create_linkedin_list","summary":"Create a prospect list from a LinkedIn SEARCH (people search / event attendees / Sales Navigator URL) or from a POST's engagers (everyone who reacted to or commented on it — preview first with preview_linkedin_post_engagers)","description":"Create a prospect list from a LinkedIn SEARCH (people search / event attendees / Sales Navigator URL) or from a POST's engagers (everyone who reacted to or commented on it — preview first with preview_linkedin_post_engagers). The import runs in the background over minutes; poll get_linkedin_list until status \"ready\". Creating a list sends nothing.\n\nRequired scope: `linkedin.write`. Risk level: `write`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.write"]}],"parameters":[{"name":"name","in":"query","required":false,"description":"List name (required for searchUrl; defaults for postUrl).","schema":{"type":"string","maxLength":140}},{"name":"searchUrl","in":"query","required":false,"description":"A linkedin.com search URL to import from. Pass this OR postUrl.","schema":{"type":"string","maxLength":1500}},{"name":"postUrl","in":"query","required":false,"description":"A LinkedIn post URL whose engagers to import. Pass this OR searchUrl.","schema":{"type":"string","maxLength":500}},{"name":"includeReactions","in":"query","required":false,"description":"postUrl only: import people who reacted. Default true.","schema":{"type":"boolean"}},{"name":"includeComments","in":"query","required":false,"description":"postUrl only: import people who commented. Default true.","schema":{"type":"boolean"}},{"name":"senderId","in":"query","required":false,"description":"Sender whose LinkedIn session performs the import. Defaults to the first available sender.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"created":{"type":"boolean","description":"Always true."},"list":{"type":"object","properties":{"id":{"type":"string","description":"List id."},"name":{"type":"string","description":"List name."},"source":{"type":"string","description":"How it was built: search | post | urls | csv."},"status":{"type":"string","description":"Import state: importing | ready."},"count":{"type":"integer","description":"Prospects in the list (grows while importing)."},"createdAt":{"type":"string","description":"ISO 8601 creation time."}},"additionalProperties":true,"required":["id","name","source","status","count","createdAt"],"description":"The new list; status \"importing\", count 0 until the background import fills it."},"note":{"type":"string","description":"Polling hint."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","created","list","note"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/lists/{listId}":{"get":{"operationId":"get_linkedin_list","summary":"One prospect list with its prospects (name, title, company, profile URL)","description":"One prospect list with its prospects (name, title, company, profile URL). While an import is running the list's status is \"importing\" and the count grows — poll until \"ready\".\n\nRequired scope: `linkedin.read`. Risk level: `read`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.read"]}],"parameters":[{"name":"listId","in":"path","required":true,"description":"List id from list_linkedin_lists.","schema":{"type":"string","maxLength":60}},{"name":"query","in":"query","required":false,"description":"Filter prospects by name, company or email.","schema":{"type":"string","maxLength":120}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"list":{"type":"object","properties":{"id":{"type":"string","description":"List id."},"name":{"type":"string","description":"List name."},"source":{"type":"string","description":"How it was built: search | post | urls | csv."},"status":{"type":"string","description":"Import state: importing | ready."},"count":{"type":"integer","description":"Prospects in the list (grows while importing)."},"createdAt":{"type":"string","description":"ISO 8601 creation time."}},"additionalProperties":true,"required":["id","name","source","status","count","createdAt"],"description":"Prospect list."},"leads":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Prospect id (leadId for set_linkedin_lead_state)."},"fullName":{"type":"string","description":"Full name."},"jobTitle":{"type":"string","description":"Job title."},"headline":{"type":"string","description":"LinkedIn headline."},"company":{"type":"string","description":"Company."},"location":{"type":"string","description":"Location."},"email":{"type":"string","description":"Email when known, else \"\"."},"linkedinUrl":{"type":"string","description":"Profile URL."}},"additionalProperties":true,"required":["id","fullName","jobTitle","headline","company","location","email","linkedinUrl"],"description":"One prospect."},"description":"Prospects on this page, sorted by name."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (capped server-side)."},"total":{"type":"integer","description":"Total rows after filtering, across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page info from lib/mcp/schema.js paginate()."}},"additionalProperties":true,"required":["ok","requestId","list","leads","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/sequences":{"get":{"operationId":"list_linkedin_sequences","summary":"LinkedIn outreach sequences (campaigns): status (draft/running/paused/finished), target list, senders, step count, enrollment counts and headline stats (invites, accepted, messages, replies)","description":"LinkedIn outreach sequences (campaigns): status (draft/running/paused/finished), target list, senders, step count, enrollment counts and headline stats (invites, accepted, messages, replies).\n\nRequired scope: `linkedin.read`. Risk level: `read`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.read"]}],"parameters":[{"name":"status","in":"query","required":false,"description":"Only sequences in this state.","schema":{"type":"string","enum":["draft","running","paused","finished"]}},{"name":"query","in":"query","required":false,"description":"Substring of the sequence name.","schema":{"type":"string","maxLength":120}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"sequences":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Sequence id."},"name":{"type":"string","description":"Sequence name."},"status":{"type":"string","enum":["draft","running","paused","finished"],"description":"Run state."},"listId":{"type":["string","null"],"description":"Target prospect list id, null when none attached."},"senderIds":{"type":"array","items":{"type":"string","description":"Sender id."},"description":"Sender account ids the sequence rotates across."},"stepCount":{"type":"integer","description":"Total steps including nested branch steps."},"counts":{"type":"object","properties":{"total":{"type":"integer","description":"Prospects enrolled at launch."},"pending":{"type":"integer","description":"Enrolled, first action not started yet."},"inprogress":{"type":"integer","description":"Mid-cadence."},"finished":{"type":"integer","description":"Completed the cadence (incl. not accepted / not connected)."},"failed":{"type":"integer","description":"Failed permanently."},"excluded":{"type":"integer","description":"Skipped at launch (exclusion list / blacklist / already contacted)."},"paused":{"type":"integer","description":"Paused individually."},"replied":{"type":"integer","description":"Replied (never re-enrolled)."}},"additionalProperties":true,"description":"Enrollment breakdown cached on the sequence; {} for a never-launched draft."},"stats":{"type":"object","additionalProperties":true,"description":"Lifetime counters for this sequence (metric → count); {} when none yet."},"schedule":{"type":"object","properties":{"days":{"type":"array","items":{"type":"integer","description":"Weekday 0-6."},"description":"Sending days, 0=Sunday … 6=Saturday."},"from":{"type":"string","description":"Daily window start, HH:MM."},"to":{"type":"string","description":"Daily window end, HH:MM."},"tzOffset":{"type":"number","description":"Timezone offset in hours for the window."}},"additionalProperties":true,"description":"Sending window."},"createdAt":{"type":"string","description":"ISO 8601 creation time."},"launchedAt":{"type":"string","description":"ISO 8601 first-launch time; \"\" when never launched."}},"additionalProperties":true,"required":["id","name","status","listId","senderIds","stepCount","counts","stats","schedule","createdAt","launchedAt"],"description":"Sequence summary."},"description":"Sequences, newest first."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (capped server-side)."},"total":{"type":"integer","description":"Total rows after filtering, across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page info from lib/mcp/schema.js paginate()."}},"additionalProperties":true,"required":["ok","requestId","sequences","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"create_linkedin_sequence","summary":"Create a LinkedIn outreach sequence as a DRAFT — nothing sends until launch_linkedin_sequence is confirmed, so creating is reversible","description":"Create a LinkedIn outreach sequence as a DRAFT — nothing sends until launch_linkedin_sequence is confirmed, so creating is reversible. steps: ordered actions, each {type, delayDays, delayHours, message, messageB (A/B variant), subject (inmail/email), withdrawAfterDays (connect)}. Types: view_profile, like_post, endorse, connect, message, inmail, send_email, and branch nodes if_connected/{connected,notConnected}, if_replied/{replied,notReplied}, if_open/{open,notOpen} whose branch keys hold sub-step arrays. Personalization tokens like {firstName} {company} work in messages. Attach a prospect list (listId from list_linkedin_lists) and senders (senderIds from list_linkedin_senders) here or later with update_linkedin_sequence.\n\nRequired scope: `linkedin.write`. Risk level: `write`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.write"]}],"parameters":[{"name":"name","in":"query","required":true,"description":"Sequence name.","schema":{"type":"string","maxLength":140}},{"name":"steps","in":"query","required":true,"description":"Ordered steps — see the tool description for the shape.","schema":{"type":"array","maxItems":40,"items":{"type":"object"}}},{"name":"listId","in":"query","required":false,"description":"Prospect list to target (from list_linkedin_lists).","schema":{"type":"string","maxLength":60}},{"name":"excludeListId","in":"query","required":false,"description":"List whose members are excluded.","schema":{"type":"string","maxLength":60}},{"name":"senderIds","in":"query","required":false,"description":"Sender account ids to rotate across.","schema":{"type":"array","maxItems":20,"items":{"type":"string"}}},{"name":"scheduleDays","in":"query","required":false,"description":"Sending days, 0=Sunday … 6=Saturday. Default Mon-Fri.","schema":{"type":"array","maxItems":7,"items":{"type":"string"}}},{"name":"scheduleFrom","in":"query","required":false,"description":"Daily window start, HH:MM (default 09:00).","schema":{"type":"string","maxLength":5}},{"name":"scheduleTo","in":"query","required":false,"description":"Daily window end, HH:MM (default 19:00).","schema":{"type":"string","maxLength":5}},{"name":"tzOffset","in":"query","required":false,"description":"Timezone offset in hours for the window, e.g. 3 for Israel summer.","schema":{"type":"integer","minimum":-12,"maximum":14}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"created":{"type":"boolean","description":"Always true."},"sequence":{"type":"object","properties":{"id":{"type":"string","description":"Sequence id."},"name":{"type":"string","description":"Sequence name."},"status":{"type":"string","enum":["draft","running","paused","finished"],"description":"Run state."},"listId":{"type":["string","null"],"description":"Target prospect list id, null when none attached."},"senderIds":{"type":"array","items":{"type":"string","description":"Sender id."},"description":"Sender account ids the sequence rotates across."},"stepCount":{"type":"integer","description":"Total steps including nested branch steps."},"counts":{"type":"object","properties":{"total":{"type":"integer","description":"Prospects enrolled at launch."},"pending":{"type":"integer","description":"Enrolled, first action not started yet."},"inprogress":{"type":"integer","description":"Mid-cadence."},"finished":{"type":"integer","description":"Completed the cadence (incl. not accepted / not connected)."},"failed":{"type":"integer","description":"Failed permanently."},"excluded":{"type":"integer","description":"Skipped at launch (exclusion list / blacklist / already contacted)."},"paused":{"type":"integer","description":"Paused individually."},"replied":{"type":"integer","description":"Replied (never re-enrolled)."}},"additionalProperties":true,"description":"Enrollment breakdown cached on the sequence; {} for a never-launched draft."},"stats":{"type":"object","additionalProperties":true,"description":"Lifetime counters for this sequence (metric → count); {} when none yet."},"schedule":{"type":"object","properties":{"days":{"type":"array","items":{"type":"integer","description":"Weekday 0-6."},"description":"Sending days, 0=Sunday … 6=Saturday."},"from":{"type":"string","description":"Daily window start, HH:MM."},"to":{"type":"string","description":"Daily window end, HH:MM."},"tzOffset":{"type":"number","description":"Timezone offset in hours for the window."}},"additionalProperties":true,"description":"Sending window."},"createdAt":{"type":"string","description":"ISO 8601 creation time."},"launchedAt":{"type":"string","description":"ISO 8601 first-launch time; \"\" when never launched."},"steps":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["view_profile","like_post","endorse","connect","if_connected","if_open","if_replied","message","inmail","send_email"],"description":"Step / branch-node type."},"delayDays":{"type":"integer","description":"Days to wait before this step."},"delayHours":{"type":"integer","description":"Extra hours to wait before this step."},"message":{"type":"string","description":"Message / invite note text (≤2000 chars), only when set."},"messageB":{"type":"string","description":"A/B variant B text, only when set."},"subject":{"type":"string","description":"InMail / email subject, only when set."},"fallback":{"type":"string","description":"Fallback text, only when set."},"withdrawAfterDays":{"type":"number","description":"connect: withdraw the invite after N days, only when > 0."},"connected":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"notConnected":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"replied":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"notReplied":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"open":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"notOpen":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."}},"additionalProperties":true,"required":["type","delayDays","delayHours"],"description":"One sequence step."},"description":"Ordered steps with message text and branch sub-flows."},"excludeListId":{"type":"string","description":"Exclusion list id, only when set."}},"additionalProperties":true,"required":["id","name","status","listId","senderIds","stepCount","counts","stats","schedule","createdAt","launchedAt","steps"],"description":"Sequence with its steps."},"stepsDropped":{"type":"integer","description":"Steps trimmed by the server (depth/count limits); 0 = all kept."},"note":{"type":"string","description":"Draft reminder and what is still missing before launch."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","created","sequence","stepsDropped","note"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/sequences/{id}":{"get":{"operationId":"get_linkedin_sequence","summary":"One sequence in full: every step with its message text (including A/B variant B and branch sub-flows), schedule window, live per-prospect breakdown (pending / in progress / replied / failed), per-sender stats, A/B variant results and a 30-day daily series","description":"One sequence in full: every step with its message text (including A/B variant B and branch sub-flows), schedule window, live per-prospect breakdown (pending / in progress / replied / failed), per-sender stats, A/B variant results and a 30-day daily series.\n\nRequired scope: `linkedin.read`. Risk level: `read`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Sequence id from list_linkedin_sequences.","schema":{"type":"string","maxLength":60}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"sequence":{"type":"object","properties":{"id":{"type":"string","description":"Sequence id."},"name":{"type":"string","description":"Sequence name."},"status":{"type":"string","enum":["draft","running","paused","finished"],"description":"Run state."},"listId":{"type":["string","null"],"description":"Target prospect list id, null when none attached."},"senderIds":{"type":"array","items":{"type":"string","description":"Sender id."},"description":"Sender account ids the sequence rotates across."},"stepCount":{"type":"integer","description":"Total steps including nested branch steps."},"counts":{"type":"object","properties":{"total":{"type":"integer","description":"Prospects enrolled at launch."},"pending":{"type":"integer","description":"Enrolled, first action not started yet."},"inprogress":{"type":"integer","description":"Mid-cadence."},"finished":{"type":"integer","description":"Completed the cadence (incl. not accepted / not connected)."},"failed":{"type":"integer","description":"Failed permanently."},"excluded":{"type":"integer","description":"Skipped at launch (exclusion list / blacklist / already contacted)."},"paused":{"type":"integer","description":"Paused individually."},"replied":{"type":"integer","description":"Replied (never re-enrolled)."}},"additionalProperties":true,"description":"Enrollment breakdown cached on the sequence; {} for a never-launched draft."},"stats":{"type":"object","additionalProperties":true,"description":"Lifetime counters for this sequence (metric → count); {} when none yet."},"schedule":{"type":"object","properties":{"days":{"type":"array","items":{"type":"integer","description":"Weekday 0-6."},"description":"Sending days, 0=Sunday … 6=Saturday."},"from":{"type":"string","description":"Daily window start, HH:MM."},"to":{"type":"string","description":"Daily window end, HH:MM."},"tzOffset":{"type":"number","description":"Timezone offset in hours for the window."}},"additionalProperties":true,"description":"Sending window."},"createdAt":{"type":"string","description":"ISO 8601 creation time."},"launchedAt":{"type":"string","description":"ISO 8601 first-launch time; \"\" when never launched."},"steps":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["view_profile","like_post","endorse","connect","if_connected","if_open","if_replied","message","inmail","send_email"],"description":"Step / branch-node type."},"delayDays":{"type":"integer","description":"Days to wait before this step."},"delayHours":{"type":"integer","description":"Extra hours to wait before this step."},"message":{"type":"string","description":"Message / invite note text (≤2000 chars), only when set."},"messageB":{"type":"string","description":"A/B variant B text, only when set."},"subject":{"type":"string","description":"InMail / email subject, only when set."},"fallback":{"type":"string","description":"Fallback text, only when set."},"withdrawAfterDays":{"type":"number","description":"connect: withdraw the invite after N days, only when > 0."},"connected":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"notConnected":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"replied":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"notReplied":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"open":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"notOpen":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."}},"additionalProperties":true,"required":["type","delayDays","delayHours"],"description":"One sequence step."},"description":"Ordered steps with message text and branch sub-flows."},"excludeListId":{"type":"string","description":"Exclusion list id, only when set."},"breakdown":{"type":"object","properties":{"total":{"type":"integer","description":"Prospects with a progress record."},"pending":{"type":"integer","description":"Active, not started."},"inprogress":{"type":"integer","description":"Active, mid-cadence."},"finished":{"type":"integer","description":"Done (replied / finished / not accepted / not connected)."},"failed":{"type":"integer","description":"Failed."},"excluded":{"type":"integer","description":"Excluded at launch."},"paused":{"type":"integer","description":"Paused individually."},"replied":{"type":"integer","description":"Has replied at any point."},"accepted":{"type":"integer","description":"Accepted the connection invite."}},"additionalProperties":true,"description":"Live per-prospect breakdown computed from progress records."},"abVariants":{"type":"object","additionalProperties":true,"description":"A/B results: stepId → { A: {sent, won}, B: {sent, won} }; won = accepted (connect) or replied."},"daily":{"type":"object","additionalProperties":true,"description":"Newest 30 days: \"YYYY-MM-DD\" → { metric → count }."},"senderStats":{"type":"object","additionalProperties":true,"description":"senderId → { metric → count } for this sequence."}},"additionalProperties":true,"required":["id","name","status","listId","senderIds","stepCount","counts","stats","schedule","createdAt","launchedAt","steps","breakdown","abVariants","daily","senderStats"],"description":"Sequence with steps, live breakdown and analytics."}},"additionalProperties":true,"required":["ok","requestId","sequence"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/post-engagers":{"get":{"operationId":"preview_linkedin_post_engagers","summary":"Who engaged with a LinkedIn post (reactions and comments) — counts and a sample of names, WITHOUT creating anything","description":"Who engaged with a LinkedIn post (reactions and comments) — counts and a sample of names, WITHOUT creating anything. Use before create_linkedin_list with postUrl to see who you would import.\n\nRequired scope: `linkedin.read`. Risk level: `read`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.read"]}],"parameters":[{"name":"postUrl","in":"query","required":true,"description":"LinkedIn post URL (feed/update/… or /posts/…-activity-…).","schema":{"type":"string","maxLength":500}},{"name":"senderId","in":"query","required":false,"description":"Sender whose LinkedIn session reads the post. Defaults to the first available sender.","schema":{"type":"string","maxLength":60}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"postId":{"type":"string","description":"Resolved post URN, e.g. urn:li:activity:7…"},"engagers":{"type":"object","properties":{"reactions":{"type":"object","properties":{"count":{"type":"integer","description":"Engagers on the first page (≤25)."},"more":{"type":"boolean","description":"True when more pages exist."},"sample":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Full name."},"headline":{"type":"string","description":"Headline (≤80 chars)."}},"additionalProperties":true,"description":"Engager."},"description":"Up to 6 names."},"error":{"type":"string","description":"Provider error, only on failure."}},"additionalProperties":true,"description":"People who reacted (or {error} if the lookup failed)."},"comments":{"type":"object","properties":{"count":{"type":"integer","description":"Engagers on the first page (≤25)."},"more":{"type":"boolean","description":"True when more pages exist."},"sample":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Full name."},"headline":{"type":"string","description":"Headline (≤80 chars)."}},"additionalProperties":true,"description":"Engager."},"description":"Up to 6 names."},"error":{"type":"string","description":"Provider error, only on failure."}},"additionalProperties":true,"description":"People who commented (or {error} if the lookup failed)."}},"additionalProperties":true,"required":["reactions","comments"],"description":"Per engagement kind: count of the first page, whether more exist, a sample of names."}},"additionalProperties":true,"required":["ok","requestId","postId","engagers"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/inbox":{"get":{"operationId":"list_linkedin_inbox","summary":"The unified LinkedIn inbox across every connected sender: conversation threads with the counterpart's name/company, last-message time, unread state, tags and assignee","description":"The unified LinkedIn inbox across every connected sender: conversation threads with the counterpart's name/company, last-message time, unread state, tags and assignee. Reading the LIST marks nothing read.\n\nRequired scope: `linkedin.read`. Risk level: `read`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.read"]}],"parameters":[{"name":"unreadOnly","in":"query","required":false,"description":"Only unread threads.","schema":{"type":"boolean","default":false}},{"name":"query","in":"query","required":false,"description":"Filter by counterpart name, company or snippet.","schema":{"type":"string","maxLength":120}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"threads":{"type":"array","items":{"type":"object","properties":{"chatId":{"type":"string","description":"Thread id (pass to get_linkedin_conversation / send_linkedin_message)."},"senderId":{"type":"string","description":"Connected sender the thread belongs to."},"senderName":{"type":"string","description":"That sender's display name."},"name":{"type":"string","description":"Counterpart name."},"headline":{"type":"string","description":"Counterpart headline."},"company":{"type":"string","description":"Counterpart company."},"providerId":{"type":"string","description":"Counterpart provider id (for profile resolution), only when known."},"lastAt":{"type":"string","description":"ISO 8601 time of the last message; \"\" if unknown."},"snippet":{"type":"string","description":"Last message text (≤240 chars), only when available."},"unread":{"type":"boolean","description":"Thread has unread messages."},"favorite":{"type":"boolean","description":"Starred locally."},"tags":{"type":"array","items":{"type":"string","description":"Tag."},"description":"Local tags."},"assignee":{"type":"string","description":"Assigned team member, only when set."}},"additionalProperties":true,"required":["chatId","senderId","senderName","name","headline","company","lastAt","unread","favorite","tags"],"description":"One inbox conversation."},"description":"Conversations, newest first (≤200 across all senders)."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (capped server-side)."},"total":{"type":"integer","description":"Total rows after filtering, across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page info from lib/mcp/schema.js paginate()."},"live":{"type":"boolean","description":"True when the LinkedIn provider is configured."}},"additionalProperties":true,"required":["ok","requestId","threads","pagination","live"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/inbox/messages":{"get":{"operationId":"get_linkedin_conversation","summary":"The messages of one LinkedIn conversation (newest 100), plus the counterpart's profile when resolvable","description":"The messages of one LinkedIn conversation (newest 100), plus the counterpart's profile when resolvable. NOTE: opening a conversation marks it READ on LinkedIn itself, exactly as in the app.\n\nRequired scope: `linkedin.read`. Risk level: `read`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.read"]}],"parameters":[{"name":"senderId","in":"query","required":true,"description":"The sender the thread belongs to (from list_linkedin_inbox).","schema":{"type":"string","maxLength":60}},{"name":"chatId","in":"query","required":true,"description":"Thread id from list_linkedin_inbox.","schema":{"type":"string","maxLength":120}},{"name":"providerId","in":"query","required":false,"description":"Counterpart provider id from the thread, to resolve their profile.","schema":{"type":"string","maxLength":120}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"fromMe":{"type":"boolean","description":"Sent by the sender (us)."},"text":{"type":"string","description":"Message text (≤4000 chars)."},"at":{"type":"string","description":"ISO 8601 time; \"\" if unknown."}},"additionalProperties":true,"required":["fromMe","text","at"],"description":"One message."},"description":"Newest 100 messages, oldest first."},"profile":{"type":["object","null"],"properties":{"name":{"type":"string","description":"Full name."},"headline":{"type":"string","description":"Headline."},"company":{"type":"string","description":"Company."},"linkedinUrl":{"type":"string","description":"Profile URL."}},"additionalProperties":true,"required":["name","headline","company","linkedinUrl"],"description":"Counterpart profile when providerId was given and resolvable, else null."},"markedRead":{"type":"boolean","description":"Always true — opening marks the thread read on LinkedIn."}},"additionalProperties":true,"required":["ok","requestId","messages","profile","markedRead"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/overview":{"get":{"operationId":"get_linkedin_overview","summary":"The LinkedIn dashboard in one call: total invites / accepted / messages / replies, a 30-day daily series, every sequence's headline numbers and per-sender totals","description":"The LinkedIn dashboard in one call: total invites / accepted / messages / replies, a 30-day daily series, every sequence's headline numbers and per-sender totals.\n\nRequired scope: `linkedin.read`. Risk level: `read`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.read"]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"totals":{"type":"object","properties":{"views":{"type":"integer","description":"Profile views."},"likes":{"type":"integer","description":"Post likes."},"invites":{"type":"integer","description":"Connection invites sent."},"accepted":{"type":"integer","description":"Invites accepted."},"messages":{"type":"integer","description":"Messages sent."},"inmails":{"type":"integer","description":"InMails sent."},"replies":{"type":"integer","description":"Message replies received."},"inmail_replies":{"type":"integer","description":"InMail replies received."}},"additionalProperties":true,"description":"Lifetime totals across all sequences (metric → count)."},"daily":{"type":"object","additionalProperties":true,"description":"Newest 30 days merged across sequences: \"YYYY-MM-DD\" → { metric → count }."},"sequences":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Sequence id."},"name":{"type":"string","description":"Sequence name."},"status":{"type":"string","enum":["draft","running","paused","finished"],"description":"Run state."},"counts":{"type":"object","properties":{"total":{"type":"integer","description":"Prospects enrolled at launch."},"pending":{"type":"integer","description":"Enrolled, first action not started yet."},"inprogress":{"type":"integer","description":"Mid-cadence."},"finished":{"type":"integer","description":"Completed the cadence (incl. not accepted / not connected)."},"failed":{"type":"integer","description":"Failed permanently."},"excluded":{"type":"integer","description":"Skipped at launch (exclusion list / blacklist / already contacted)."},"paused":{"type":"integer","description":"Paused individually."},"replied":{"type":"integer","description":"Replied (never re-enrolled)."}},"additionalProperties":true,"description":"Enrollment breakdown cached on the sequence; {} for a never-launched draft."},"stats":{"type":"object","additionalProperties":true,"description":"Metric name → count (views, likes, invites, accepted, messages, inmails, replies, inmail_replies …)."},"launchedAt":{"type":"string","description":"ISO 8601 launch time; \"\" when never launched."}},"additionalProperties":true,"required":["id","name","status","counts","stats","launchedAt"],"description":"Sequence headline numbers."},"description":"Up to 30 sequences, most recently launched first."},"senderTotals":{"type":"object","additionalProperties":true,"description":"senderId → { metric → count } across all sequences."}},"additionalProperties":true,"required":["ok","requestId","totals","daily","sequences","senderTotals"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/send-health":{"get":{"operationId":"get_linkedin_send_health","summary":"Detects stalled outreach: running sequences whose every sender is cooling down or disconnected (with how many actions are due), and which senders are free","description":"Detects stalled outreach: running sequences whose every sender is cooling down or disconnected (with how many actions are due), and which senders are free. If canFix is true, fix_linkedin_send_health adds the free senders to the blocked sequences.\n\nRequired scope: `linkedin.read`. Risk level: `read`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.read"]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"blocked":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Sequence id."},"name":{"type":"string","description":"Sequence name."},"active":{"type":"integer","description":"Active prospects waiting."},"due":{"type":"integer","description":"Prospects whose next action is already due."},"reason":{"type":"string","enum":["disconnected","paused","cooling"],"description":"Why nothing sends."},"senders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Sender id."},"name":{"type":"string","description":"Sender name."},"status":{"type":"string","description":"available | disconnected | checkpoint | restricted …"},"paused":{"type":"boolean","description":"Manually paused."},"coolingUntil":{"type":["string","null"],"description":"ISO 8601 cooldown end, null when not cooling."},"reason":{"type":"string","description":"Throttle / restriction reason text, \"\" if none."}},"additionalProperties":true,"required":["id","name","status","paused","coolingUntil","reason"],"description":"Sender state."},"description":"The sequence's senders and their state."}},"additionalProperties":true,"required":["id","name","active","due","reason","senders"],"description":"A stalled sequence."},"description":"Running sequences with active prospects and no usable sender."},"freeSenders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Sender id."},"name":{"type":"string","description":"Sender name."}},"additionalProperties":true,"required":["id","name"],"description":"Sender."},"description":"Senders usable right now (available, not paused, not cooling)."},"totalDue":{"type":"integer","description":"Sum of due prospects across blocked sequences."},"canFix":{"type":"boolean","description":"True when something is blocked AND a free sender exists."}},"additionalProperties":true,"required":["ok","requestId","blocked","freeSenders","totalDue","canFix"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/sequences/{id}/update":{"post":{"operationId":"update_linkedin_sequence","summary":"Edit a sequence: name, steps, target list, senders or schedule","description":"Edit a sequence: name, steps, target list, senders or schedule. Only the fields you pass change; the run status is kept. Editing the steps of a RUNNING sequence affects prospects that have not reached those steps yet.\n\nRequired scope: `linkedin.write`. Risk level: `write`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Sequence id.","schema":{"type":"string","maxLength":60}},{"name":"name","in":"query","required":false,"description":"New name.","schema":{"type":"string","maxLength":140}},{"name":"steps","in":"query","required":false,"description":"FULL replacement step array (same shape as create_linkedin_sequence).","schema":{"type":"array","maxItems":40,"items":{"type":"object"}}},{"name":"listId","in":"query","required":false,"description":"New target list id.","schema":{"type":"string","maxLength":60}},{"name":"excludeListId","in":"query","required":false,"description":"New exclusion list id, or \"\" to clear.","schema":{"type":"string","maxLength":60}},{"name":"senderIds","in":"query","required":false,"description":"FULL replacement sender id list.","schema":{"type":"array","maxItems":20,"items":{"type":"string"}}},{"name":"scheduleDays","in":"query","required":false,"description":"Sending days, 0=Sunday … 6=Saturday.","schema":{"type":"array","maxItems":7,"items":{"type":"string"}}},{"name":"scheduleFrom","in":"query","required":false,"description":"Daily window start HH:MM.","schema":{"type":"string","maxLength":5}},{"name":"scheduleTo","in":"query","required":false,"description":"Daily window end HH:MM.","schema":{"type":"string","maxLength":5}},{"name":"tzOffset","in":"query","required":false,"description":"Timezone offset in hours.","schema":{"type":"integer","minimum":-12,"maximum":14}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"updated":{"type":"boolean","description":"Always true."},"sequence":{"type":"object","properties":{"id":{"type":"string","description":"Sequence id."},"name":{"type":"string","description":"Sequence name."},"status":{"type":"string","enum":["draft","running","paused","finished"],"description":"Run state."},"listId":{"type":["string","null"],"description":"Target prospect list id, null when none attached."},"senderIds":{"type":"array","items":{"type":"string","description":"Sender id."},"description":"Sender account ids the sequence rotates across."},"stepCount":{"type":"integer","description":"Total steps including nested branch steps."},"counts":{"type":"object","properties":{"total":{"type":"integer","description":"Prospects enrolled at launch."},"pending":{"type":"integer","description":"Enrolled, first action not started yet."},"inprogress":{"type":"integer","description":"Mid-cadence."},"finished":{"type":"integer","description":"Completed the cadence (incl. not accepted / not connected)."},"failed":{"type":"integer","description":"Failed permanently."},"excluded":{"type":"integer","description":"Skipped at launch (exclusion list / blacklist / already contacted)."},"paused":{"type":"integer","description":"Paused individually."},"replied":{"type":"integer","description":"Replied (never re-enrolled)."}},"additionalProperties":true,"description":"Enrollment breakdown cached on the sequence; {} for a never-launched draft."},"stats":{"type":"object","additionalProperties":true,"description":"Lifetime counters for this sequence (metric → count); {} when none yet."},"schedule":{"type":"object","properties":{"days":{"type":"array","items":{"type":"integer","description":"Weekday 0-6."},"description":"Sending days, 0=Sunday … 6=Saturday."},"from":{"type":"string","description":"Daily window start, HH:MM."},"to":{"type":"string","description":"Daily window end, HH:MM."},"tzOffset":{"type":"number","description":"Timezone offset in hours for the window."}},"additionalProperties":true,"description":"Sending window."},"createdAt":{"type":"string","description":"ISO 8601 creation time."},"launchedAt":{"type":"string","description":"ISO 8601 first-launch time; \"\" when never launched."},"steps":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["view_profile","like_post","endorse","connect","if_connected","if_open","if_replied","message","inmail","send_email"],"description":"Step / branch-node type."},"delayDays":{"type":"integer","description":"Days to wait before this step."},"delayHours":{"type":"integer","description":"Extra hours to wait before this step."},"message":{"type":"string","description":"Message / invite note text (≤2000 chars), only when set."},"messageB":{"type":"string","description":"A/B variant B text, only when set."},"subject":{"type":"string","description":"InMail / email subject, only when set."},"fallback":{"type":"string","description":"Fallback text, only when set."},"withdrawAfterDays":{"type":"number","description":"connect: withdraw the invite after N days, only when > 0."},"connected":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"notConnected":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"replied":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"notReplied":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"open":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"notOpen":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."}},"additionalProperties":true,"required":["type","delayDays","delayHours"],"description":"One sequence step."},"description":"Ordered steps with message text and branch sub-flows."},"excludeListId":{"type":"string","description":"Exclusion list id, only when set."}},"additionalProperties":true,"required":["id","name","status","listId","senderIds","stepCount","counts","stats","schedule","createdAt","launchedAt","steps"],"description":"Sequence with its steps."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","updated","sequence"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/sequences/{id}/pause":{"post":{"operationId":"pause_linkedin_sequence","summary":"Pause a running sequence — the cron stops processing its prospects until it is resumed","description":"Pause a running sequence — the cron stops processing its prospects until it is resumed. Safe and instant; resume_linkedin_sequence continues from where it stopped.\n\nRequired scope: `linkedin.write`. Risk level: `write`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Sequence id.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"paused":{"type":"boolean","description":"Always true."},"sequence":{"type":"object","properties":{"id":{"type":"string","description":"Sequence id."},"name":{"type":"string","description":"Sequence name."},"status":{"type":"string","enum":["draft","running","paused","finished"],"description":"Run state."},"listId":{"type":["string","null"],"description":"Target prospect list id, null when none attached."},"senderIds":{"type":"array","items":{"type":"string","description":"Sender id."},"description":"Sender account ids the sequence rotates across."},"stepCount":{"type":"integer","description":"Total steps including nested branch steps."},"counts":{"type":"object","properties":{"total":{"type":"integer","description":"Prospects enrolled at launch."},"pending":{"type":"integer","description":"Enrolled, first action not started yet."},"inprogress":{"type":"integer","description":"Mid-cadence."},"finished":{"type":"integer","description":"Completed the cadence (incl. not accepted / not connected)."},"failed":{"type":"integer","description":"Failed permanently."},"excluded":{"type":"integer","description":"Skipped at launch (exclusion list / blacklist / already contacted)."},"paused":{"type":"integer","description":"Paused individually."},"replied":{"type":"integer","description":"Replied (never re-enrolled)."}},"additionalProperties":true,"description":"Enrollment breakdown cached on the sequence; {} for a never-launched draft."},"stats":{"type":"object","additionalProperties":true,"description":"Lifetime counters for this sequence (metric → count); {} when none yet."},"schedule":{"type":"object","properties":{"days":{"type":"array","items":{"type":"integer","description":"Weekday 0-6."},"description":"Sending days, 0=Sunday … 6=Saturday."},"from":{"type":"string","description":"Daily window start, HH:MM."},"to":{"type":"string","description":"Daily window end, HH:MM."},"tzOffset":{"type":"number","description":"Timezone offset in hours for the window."}},"additionalProperties":true,"description":"Sending window."},"createdAt":{"type":"string","description":"ISO 8601 creation time."},"launchedAt":{"type":"string","description":"ISO 8601 first-launch time; \"\" when never launched."}},"additionalProperties":true,"required":["id","name","status","listId","senderIds","stepCount","counts","stats","schedule","createdAt","launchedAt"],"description":"Sequence summary."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","paused","sequence"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/sequences/{id}/duplicate":{"post":{"operationId":"duplicate_linkedin_sequence","summary":"Copy a sequence into a new DRAFT (same steps, list and senders, no progress)","description":"Copy a sequence into a new DRAFT (same steps, list and senders, no progress). Useful for A/B testing a variation without touching the original.\n\nRequired scope: `linkedin.write`. Risk level: `write`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Sequence id to copy.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"created":{"type":"boolean","description":"Always true."},"sequence":{"type":"object","properties":{"id":{"type":"string","description":"Sequence id."},"name":{"type":"string","description":"Sequence name."},"status":{"type":"string","enum":["draft","running","paused","finished"],"description":"Run state."},"listId":{"type":["string","null"],"description":"Target prospect list id, null when none attached."},"senderIds":{"type":"array","items":{"type":"string","description":"Sender id."},"description":"Sender account ids the sequence rotates across."},"stepCount":{"type":"integer","description":"Total steps including nested branch steps."},"counts":{"type":"object","properties":{"total":{"type":"integer","description":"Prospects enrolled at launch."},"pending":{"type":"integer","description":"Enrolled, first action not started yet."},"inprogress":{"type":"integer","description":"Mid-cadence."},"finished":{"type":"integer","description":"Completed the cadence (incl. not accepted / not connected)."},"failed":{"type":"integer","description":"Failed permanently."},"excluded":{"type":"integer","description":"Skipped at launch (exclusion list / blacklist / already contacted)."},"paused":{"type":"integer","description":"Paused individually."},"replied":{"type":"integer","description":"Replied (never re-enrolled)."}},"additionalProperties":true,"description":"Enrollment breakdown cached on the sequence; {} for a never-launched draft."},"stats":{"type":"object","additionalProperties":true,"description":"Lifetime counters for this sequence (metric → count); {} when none yet."},"schedule":{"type":"object","properties":{"days":{"type":"array","items":{"type":"integer","description":"Weekday 0-6."},"description":"Sending days, 0=Sunday … 6=Saturday."},"from":{"type":"string","description":"Daily window start, HH:MM."},"to":{"type":"string","description":"Daily window end, HH:MM."},"tzOffset":{"type":"number","description":"Timezone offset in hours for the window."}},"additionalProperties":true,"description":"Sending window."},"createdAt":{"type":"string","description":"ISO 8601 creation time."},"launchedAt":{"type":"string","description":"ISO 8601 first-launch time; \"\" when never launched."},"steps":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["view_profile","like_post","endorse","connect","if_connected","if_open","if_replied","message","inmail","send_email"],"description":"Step / branch-node type."},"delayDays":{"type":"integer","description":"Days to wait before this step."},"delayHours":{"type":"integer","description":"Extra hours to wait before this step."},"message":{"type":"string","description":"Message / invite note text (≤2000 chars), only when set."},"messageB":{"type":"string","description":"A/B variant B text, only when set."},"subject":{"type":"string","description":"InMail / email subject, only when set."},"fallback":{"type":"string","description":"Fallback text, only when set."},"withdrawAfterDays":{"type":"number","description":"connect: withdraw the invite after N days, only when > 0."},"connected":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"notConnected":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"replied":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"notReplied":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"open":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."},"notOpen":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"A step: {type, delayDays, delayHours, message?, …}."},"description":"Nested sub-steps (same shape as a step), only when non-empty."}},"additionalProperties":true,"required":["type","delayDays","delayHours"],"description":"One sequence step."},"description":"Ordered steps with message text and branch sub-flows."},"excludeListId":{"type":"string","description":"Exclusion list id, only when set."}},"additionalProperties":true,"required":["id","name","status","listId","senderIds","stepCount","counts","stats","schedule","createdAt","launchedAt","steps"],"description":"The new DRAFT copy (name suffixed \" (copy)\")."},"note":{"type":"string","description":"Reminder that the copy is a draft on the same list/senders."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","created","sequence","note"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/sequences/{id}/lead":{"post":{"operationId":"set_linkedin_lead_state","summary":"Manage ONE prospect inside a sequence: pause them, resume them, or stop their cadence for good (op \"stop\" is how you exclude someone who asked to be left alone)","description":"Manage ONE prospect inside a sequence: pause them, resume them, or stop their cadence for good (op \"stop\" is how you exclude someone who asked to be left alone).\n\nRequired scope: `linkedin.write`. Risk level: `write`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Sequence id.","schema":{"type":"string","maxLength":60}},{"name":"leadId","in":"query","required":true,"description":"Prospect id from get_linkedin_list.","schema":{"type":"string","maxLength":60}},{"name":"op","in":"query","required":true,"description":"What to do.","schema":{"type":"string","enum":["pause","resume","stop"]}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","description":"Always true."},"requestId":{"type":"string"},"progress":{"type":"object","properties":{"status":{"type":"string","description":"active (resumed) | paused | finished (stopped)."}},"additionalProperties":true,"required":["status"],"description":"The prospect's new cadence state."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","ok","progress"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/send-health/fix":{"post":{"operationId":"fix_linkedin_send_health","summary":"One-click fix for a stalled queue: adds every currently-usable sender to the running sequences whose own senders are all cooling down, so the cron's rebalance has somewhere to move waiting prospects","description":"One-click fix for a stalled queue: adds every currently-usable sender to the running sequences whose own senders are all cooling down, so the cron's rebalance has somewhere to move waiting prospects. Run get_linkedin_send_health first; only acts on sequences it reported as blocked.\n\nRequired scope: `linkedin.write`. Risk level: `write`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.write"]}],"parameters":[{"name":"sequenceIds","in":"query","required":false,"description":"Limit the fix to these sequences. Default: every blocked one.","schema":{"type":"array","maxItems":50,"items":{"type":"string"}}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"fixed":{"type":"boolean","description":"True when at least one sequence was changed."},"changed":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Sequence id."},"name":{"type":"string","description":"Sequence name."},"added":{"type":"integer","description":"Senders added."},"addedNames":{"type":"array","items":{"type":"string","description":"Sender name."},"description":"Names of the added senders."}},"additionalProperties":true,"required":["id","name","added","addedNames"],"description":"One changed sequence."},"description":"Sequences that received extra senders."},"sendersAdded":{"type":"array","items":{"type":"string","description":"Sender name."},"description":"Names of every free sender considered."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","fixed","changed","sendersAdded"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/sequences/{id}/launch":{"post":{"operationId":"launch_linkedin_sequence","summary":"Launch a sequence: enrolls the target list's prospects and real LinkedIn outreach begins within minutes (staggered, inside the schedule window, under per-sender daily caps)","description":"Launch a sequence: enrolls the target list's prospects and real LinkedIn outreach begins within minutes (staggered, inside the schedule window, under per-sender daily caps). PREVIEW FIRST: called without confirm it changes nothing and reports how many prospects would enroll, the senders, the steps and any blockers (no list / no sender / empty list). People who already replied are never re-enrolled. Relaunching an already-run sequence re-enrolls unfinished prospects from step 0.\n\nRequired scope: `linkedin.send`. Risk level: `high`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.send"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Sequence id.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["linkedin_sequence"],"description":"Preview only."},"targetId":{"type":"string","description":"Preview only: sequence id."},"sequence":{"description":"Preview: the sequence NAME (string). Run: the launched sequence summary object (status \"running\")."},"currentStatus":{"type":"string","description":"Preview only: status before launching."},"prospects":{"type":"integer","description":"Preview only: prospects on the target list (0 if none/empty)."},"senders":{"type":"integer","description":"Preview only: number of attached senders."},"steps":{"type":"integer","description":"Preview only: total steps."},"schedule":{"type":"object","properties":{"days":{"type":"array","items":{"type":"integer","description":"Weekday 0-6."},"description":"Sending days, 0=Sunday … 6=Saturday."},"from":{"type":"string","description":"Daily window start, HH:MM."},"to":{"type":"string","description":"Daily window end, HH:MM."},"tzOffset":{"type":"number","description":"Timezone offset in hours for the window."}},"additionalProperties":true,"description":"Preview only: sending window."},"alreadyRepliedKept":{"type":"integer","description":"Preview only: prospects who already replied and will not be re-enrolled."},"problems":{"type":"array","items":{"type":"string","description":"Blocker."},"description":"Preview only: blockers; empty = ready."},"summary":{"type":"string","description":"Preview only: human summary."},"launched":{"type":"boolean","description":"Run only: always true."},"enrolled":{"type":"integer","description":"Run only: prospects enrolled."},"excluded":{"type":"integer","description":"Run only: prospects skipped by exclusions / blacklist."},"keptReplied":{"type":"integer","description":"Run only: prospects left untouched because they had replied."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","sequence"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/sequences/{id}/resume":{"post":{"operationId":"resume_linkedin_sequence","summary":"Resume a paused sequence — the cron continues each unfinished prospect from exactly where they stopped (no re-enrollment, no restart from step 0; that is what launch does)","description":"Resume a paused sequence — the cron continues each unfinished prospect from exactly where they stopped (no re-enrollment, no restart from step 0; that is what launch does). PREVIEW FIRST: without confirm it reports how many prospects are pending / mid-cadence.\n\nRequired scope: `linkedin.send`. Risk level: `high`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.send"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Sequence id.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["linkedin_sequence"],"description":"Preview only."},"targetId":{"type":"string","description":"Preview only: sequence id."},"sequence":{"description":"Preview: the sequence NAME (string). Run: the sequence summary object (status \"running\")."},"currentStatus":{"type":"string","description":"Preview only: status before resuming."},"pending":{"type":"integer","description":"Preview only: prospects not started yet."},"inProgress":{"type":"integer","description":"Preview only: prospects mid-cadence."},"summary":{"type":"string","description":"Preview only: human summary."},"resumed":{"type":"boolean","description":"Run only: always true."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","sequence"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/inbox/send":{"post":{"operationId":"send_linkedin_message","summary":"Reply in an existing LinkedIn conversation as one of the connected senders","description":"Reply in an existing LinkedIn conversation as one of the connected senders. PREVIEW FIRST: without confirm it changes nothing and echoes exactly which sender says what in which thread. A sent LinkedIn message cannot be unsent.\n\nRequired scope: `linkedin.send`. Risk level: `high`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.send"]}],"parameters":[{"name":"senderId","in":"query","required":true,"description":"Sender the thread belongs to.","schema":{"type":"string","maxLength":60}},{"name":"chatId","in":"query","required":true,"description":"Thread id from list_linkedin_inbox.","schema":{"type":"string","maxLength":120}},{"name":"text","in":"query","required":true,"description":"The message text.","schema":{"type":"string","maxLength":8000}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["linkedin_chat"],"description":"Preview only."},"targetId":{"type":"string","description":"Preview only: the chat id."},"from":{"type":"string","description":"Preview only: sender display name."},"chatId":{"type":"string","description":"Thread id the message goes to / went to."},"text":{"type":"string","description":"Preview only: the exact text that will be sent."},"summary":{"type":"string","description":"Preview only: human summary."},"sent":{"type":"boolean","description":"Run only: always true."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","chatId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/lists/import-urls":{"post":{"operationId":"import_linkedin_leads","summary":"Add specific LinkedIn profiles (by URL, max 40) to a prospect list — a new one or an existing one","description":"Add specific LinkedIn profiles (by URL, max 40) to a prospect list — a new one or an existing one. HIGH IMPACT because adding to a list a RUNNING sequence targets enrolls the new prospects immediately and outreach to them starts within minutes. PREVIEW FIRST: without confirm it reports the target list, how many URLs are valid, and exactly which running sequences would start contacting them.\n\nRequired scope: `linkedin.write`. Risk level: `high`.","tags":["linkedin"],"security":[{"bearerAuth":["linkedin.write"]}],"parameters":[{"name":"urls","in":"query","required":true,"description":"linkedin.com/in/… profile URLs.","schema":{"type":"array","maxItems":40,"items":{"type":"string"}}},{"name":"listId","in":"query","required":false,"description":"Existing list to add to. Omit to create a new list.","schema":{"type":"string","maxLength":60}},{"name":"name","in":"query","required":false,"description":"Name for the new list when listId is omitted.","schema":{"type":"string","maxLength":140}},{"name":"senderId","in":"query","required":false,"description":"Sender whose session resolves the profiles. Defaults to the first available.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["linkedin_list"],"description":"Preview only."},"targetId":{"type":"string","description":"Preview only: existing list id or \"(new list)\"."},"profiles":{"type":"integer","description":"Preview only: valid linkedin.com/in/ URLs (max 40)."},"invalidDropped":{"type":"integer","description":"Preview only: URLs ignored as invalid."},"list":{"description":"Preview: target list NAME (string). Run: the list object after import (id, name, source, status, count, createdAt)."},"resolvingSender":{"type":"string","description":"Preview only: sender id whose session resolves the profiles."},"enrollsIntoRunning":{"type":"array","items":{"type":"string","description":"Sequence name."},"description":"Preview only: names of RUNNING sequences on this list that would enroll the new prospects."},"summary":{"type":"string","description":"Preview only: human summary."},"imported":{"type":"boolean","description":"Run only: always true."},"requested":{"type":"integer","description":"Run only: URLs submitted."},"resolved":{"type":"integer","description":"Run only: URLs resolved to a profile."},"added":{"type":"integer","description":"Run only: new prospects added (after dedupe)."},"enrolledIntoRunning":{"type":"integer","description":"Run only: prospects enrolled into running sequences (outreach starts now)."},"startedSequences":{"type":"array","items":{"type":"string","description":"Sequence name."},"description":"Run only: names of the running sequences that enrolled them."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","list"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/sequences/{id}/delete":{"post":{"operationId":"delete_linkedin_sequence","summary":"Delete a sequence and all its per-prospect progress and stats","description":"Delete a sequence and all its per-prospect progress and stats. IRREVERSIBLE — pause_linkedin_sequence is almost always the better choice. The prospect list is kept. PREVIEW FIRST.\n\nRequired scope: `records.delete`. Risk level: `high`.","tags":["records"],"security":[{"bearerAuth":["records.delete"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Sequence id.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["linkedin_sequence"],"description":"Preview only."},"targetId":{"type":"string","description":"Preview only: sequence id."},"sequence":{"type":"string","description":"Preview only: sequence name."},"status":{"type":"string","enum":["draft","running","paused","finished"],"description":"Preview only: current run state."},"counts":{"type":"object","properties":{"total":{"type":"integer","description":"Prospects enrolled at launch."},"pending":{"type":"integer","description":"Enrolled, first action not started yet."},"inprogress":{"type":"integer","description":"Mid-cadence."},"finished":{"type":"integer","description":"Completed the cadence (incl. not accepted / not connected)."},"failed":{"type":"integer","description":"Failed permanently."},"excluded":{"type":"integer","description":"Skipped at launch (exclusion list / blacklist / already contacted)."},"paused":{"type":"integer","description":"Paused individually."},"replied":{"type":"integer","description":"Replied (never re-enrolled)."}},"additionalProperties":true,"description":"Preview only: enrollment breakdown that will be lost."},"summary":{"type":"string","description":"Preview only: human summary."},"deleted":{"type":"boolean","description":"Run only: always true."},"id":{"type":"string","description":"Run only: deleted sequence id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/linkedin/lists/{listId}/delete":{"post":{"operationId":"delete_linkedin_list","summary":"Delete a prospect list and its prospects","description":"Delete a prospect list and its prospects. IRREVERSIBLE. PREVIEW FIRST: without confirm it reports the prospect count and warns if any sequence still targets the list.\n\nRequired scope: `records.delete`. Risk level: `high`.","tags":["records"],"security":[{"bearerAuth":["records.delete"]}],"parameters":[{"name":"listId","in":"path","required":true,"description":"List id.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"targetType":{"type":"string","enum":["linkedin_list"],"description":"Preview only."},"targetId":{"type":"string","description":"Preview only: list id."},"list":{"type":"string","description":"Preview only: list name."},"prospects":{"type":"integer","description":"Preview only: prospects that will be deleted with it."},"usedBySequences":{"type":"array","items":{"type":"string","description":"Sequence name (status)."},"description":"Preview only: \"name (status)\" of sequences still targeting the list."},"summary":{"type":"string","description":"Preview only: human summary."},"deleted":{"type":"boolean","description":"Run only: always true."},"listId":{"type":"string","description":"Run only: deleted list id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/wallet":{"get":{"operationId":"get_wallet_overview","summary":"Overview of the Wallet loyalty module: every club card (loyalty / stamps / coupon / gift / membership) with its exact funnel — members, installed in Apple/Google Wallet, visited, redeemed, open points — plus recent club activity (joins, scans, redemptions, pushes)","description":"Overview of the Wallet loyalty module: every club card (loyalty / stamps / coupon / gift / membership) with its exact funnel — members, installed in Apple/Google Wallet, visited, redeemed, open points — plus recent club activity (joins, scans, redemptions, pushes). Use it for \"how is the club doing\", \"how many joined\", \"which card performs best\". Numbers are exact, derived from the passes themselves.\n\nRequired scope: `wallet.read`. Risk level: `read`.","tags":["wallet"],"security":[{"bearerAuth":["wallet.read"]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"cards":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Card template id; pass as cardId to search_wallet_members."},"name":{"type":"string","description":"Card name."},"type":{"type":"string","description":"Card type, e.g. loyalty, stamp, gift, coupon."},"brand":{"type":["string","null"],"description":"Brand label, or null."},"members":{"type":"integer","description":"Members who joined this card."},"installedInWallets":{"type":"integer","description":"Members who added it to Apple/Google Wallet."},"visited":{"type":"integer","description":"Members scanned at least once."},"redeemed":{"type":"integer","description":"Members who redeemed a reward."},"openPoints":{"type":"number","description":"Outstanding points across members."}},"additionalProperties":true,"required":["id","name","type","brand","members","installedInWallets","visited","redeemed","openPoints"]},"description":"Wallet card templates (loyalty / stamp / gift / coupon) with their funnel."},"installedDevices":{"type":"integer","description":"Devices with a pass installed, across all cards."},"recentActivity":{"type":"array","items":{"type":"object","properties":{"op":{"type":"string","description":"Operation, e.g. issue, push, nudge, birthday, season-on."},"at":{"type":["string","null"],"description":"ISO 8601, or null."},"member":{"type":["string","null"],"description":"Member email when the entry concerns one, else null."},"card":{"type":["string","null"],"description":"Card template id, or null."},"members":{"type":"integer","description":"Members affected (bulk operations only)."},"text":{"type":"string","description":"Message text sent (push/nudge only)."}},"additionalProperties":true,"required":["op","at","member","card"]},"description":"Last 10 ledger entries, newest first."}},"additionalProperties":true,"required":["ok","requestId","cards","installedDevices","recentActivity"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/wallet/members":{"get":{"operationId":"search_wallet_members","summary":"Search club members by name, email, phone or member id, optionally within one card","description":"Search club members by name, email, phone or member id, optionally within one card. Returns per member: tier, points/stamps/balance, how many devices installed the pass, join source (utm), join date and last visit. Use get_wallet_overview first to learn the card ids.\n\nRequired scope: `wallet.read`. Risk level: `read`.","tags":["wallet"],"security":[{"bearerAuth":["wallet.read"]}],"parameters":[{"name":"query","in":"query","required":false,"description":"Free text: name, email, phone or member id. Empty = newest members.","schema":{"type":"string","maxLength":120}},{"name":"cardId","in":"query","required":false,"description":"Restrict to one club card (id from get_wallet_overview).","schema":{"type":"string","maxLength":40}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"total":{"type":"integer","description":"Members matching the query before paging (server caps the read at 500)."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"1-based page number that was returned."},"pageSize":{"type":"integer","description":"Rows per page (max 100)."},"total":{"type":"integer","description":"Total matching rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"True when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the (already filtered and sorted) result set."},"members":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Pass id."},"name":{"type":["string","null"],"description":"Member name, or null."},"email":{"type":"string","description":"Member email."},"phone":{"type":["string","null"],"description":"Member phone, or null."},"cardId":{"type":"string","description":"Card template id."},"status":{"type":"string","description":"Pass status, e.g. active, revoked."},"tier":{"type":["string","null"],"description":"Loyalty tier, or null."},"points":{"type":"number","description":"Current points balance."},"stamps":{"type":"number","description":"Current stamp count."},"balance":{"type":"number","description":"Gift-card balance."},"installedDevices":{"type":"integer","description":"Devices the pass is installed on."},"source":{"type":["string","null"],"description":"Join source (UTM source or issue source), or null."},"joinedAt":{"type":["string","null"],"description":"ISO 8601 issue time, or null."},"lastVisitAt":{"type":["string","null"],"description":"ISO 8601 of the last scan, or null."}},"additionalProperties":true,"required":["id","name","email","phone","cardId","status","tier","points","stamps","balance","installedDevices","source","joinedAt","lastVisitAt"]},"description":"Matching wallet members (passes), most recently joined first."}},"additionalProperties":true,"required":["ok","requestId","total","pagination","members"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/projects":{"get":{"operationId":"list_projects","summary":"The Projects boards visible to this user: name, key, item count, groups, columns and the status labels each board uses","description":"The Projects boards visible to this user: name, key, item count, groups, columns and the status labels each board uses. Call this first — create/update tools need a projectId, valid status names and group/column ids from here.\n\nRequired scope: `projects.read`. Risk level: `read`.","tags":["projects"],"security":[{"bearerAuth":["projects.read"]}],"parameters":[{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"projects":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Project (board) id."},"name":{"type":"string","description":"Board name (\"\" if unset)."},"key":{"type":"string","description":"Short key used in item refs, e.g. \"PROJ\" → PROJ-12."},"color":{"type":"string","description":"Board colour, hex or \"\"."},"itemCount":{"type":"integer","description":"Number of items on the board."},"groups":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Group id."},"name":{"type":"string","description":"Group name."}},"additionalProperties":true,"required":["id"]},"description":"Row groups (sections) of the board."},"columns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Column id (accepted in create/update values)."},"title":{"type":"string","description":"Column title (also accepted in values)."},"type":{"type":"string","description":"Column type, e.g. status, people, date, text, number."}},"additionalProperties":true,"required":["id"]},"description":"Board columns; values are keyed by column title in item.values."},"statuses":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Status label name."},"done":{"type":"boolean","description":"true when this status means completed."},"cancelled":{"type":"boolean","description":"true when this status means cancelled."}},"additionalProperties":true,"required":["name","done","cancelled"]},"description":"Labels of the status column; use these names for item status."},"visibility":{"type":"string","description":"Board visibility, \"shared\" by default."},"owner":{"type":"string","description":"Owner email (\"\" if unknown)."}},"additionalProperties":true,"required":["id","name","key","color","itemCount","groups","columns","statuses","visibility","owner"],"description":"A project board (its metadata, not its items)."},"description":"Boards visible to this token."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"Current page, 1-based."},"pageSize":{"type":"integer","description":"Rows per page after clamping."},"total":{"type":"integer","description":"Total rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"true when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the list (lib/mcp/schema.js paginate)."}},"additionalProperties":true,"required":["ok","requestId","projects","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"create_project","summary":"Create a new board with a People column, a Status column (default labels Backlog / Todo / In Progress / Done, or your own), a Due date column and groups (default To-Do / Completed)","description":"Create a new board with a People column, a Status column (default labels Backlog / Todo / In Progress / Done, or your own), a Due date column and groups (default To-Do / Completed). Reversible — a board can be deleted in the app.\n\nRequired scope: `projects.write`. Risk level: `write`.","tags":["projects"],"security":[{"bearerAuth":["projects.write"]}],"parameters":[{"name":"name","in":"query","required":true,"description":"Board name.","schema":{"type":"string","maxLength":120}},{"name":"key","in":"query","required":false,"description":"Short prefix for item refs, e.g. CAMP. Default: derived from the name.","schema":{"type":"string","maxLength":6}},{"name":"statuses","in":"query","required":false,"description":"Status labels in order (first = default for new items; a label named \"Done\" counts as done).","schema":{"type":"array","maxItems":12,"items":{"type":"string"}}},{"name":"groups","in":"query","required":false,"description":"Group names in order.","schema":{"type":"array","maxItems":12,"items":{"type":"string"}}},{"name":"color","in":"query","required":false,"description":"Hex color for the board.","schema":{"type":"string","maxLength":9}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"created":{"type":"boolean","description":"Always true on success."},"project":{"type":"object","properties":{"id":{"type":"string","description":"Project (board) id."},"name":{"type":"string","description":"Board name (\"\" if unset)."},"key":{"type":"string","description":"Short key used in item refs, e.g. \"PROJ\" → PROJ-12."},"color":{"type":"string","description":"Board colour, hex or \"\"."},"itemCount":{"type":"integer","description":"Number of items on the board."},"groups":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Group id."},"name":{"type":"string","description":"Group name."}},"additionalProperties":true,"required":["id"]},"description":"Row groups (sections) of the board."},"columns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Column id (accepted in create/update values)."},"title":{"type":"string","description":"Column title (also accepted in values)."},"type":{"type":"string","description":"Column type, e.g. status, people, date, text, number."}},"additionalProperties":true,"required":["id"]},"description":"Board columns; values are keyed by column title in item.values."},"statuses":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Status label name."},"done":{"type":"boolean","description":"true when this status means completed."},"cancelled":{"type":"boolean","description":"true when this status means cancelled."}},"additionalProperties":true,"required":["name","done","cancelled"]},"description":"Labels of the status column; use these names for item status."},"visibility":{"type":"string","description":"Board visibility, \"shared\" by default."},"owner":{"type":"string","description":"Owner email (\"\" if unknown)."}},"additionalProperties":true,"required":["id","name","key","color","itemCount","groups","columns","statuses","visibility","owner"],"description":"A project board (its metadata, not its items)."},"targetType":{"type":"string","enum":["project"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"New board id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","created","project","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/projects/{id}":{"get":{"operationId":"get_project","summary":"One board with its items: each item has a ref (KEY-number), title, status, priority, assignees, due date, group, and the values of the board's custom columns keyed by column title","description":"One board with its items: each item has a ref (KEY-number), title, status, priority, assignees, due date, group, and the values of the board's custom columns keyed by column title. Filter by status or group; paged.\n\nRequired scope: `projects.read`. Risk level: `read`.","tags":["projects"],"security":[{"bearerAuth":["projects.read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Project (board) id from list_projects.","schema":{"type":"string","maxLength":60}},{"name":"status","in":"query","required":false,"description":"Only items in this status (exact label).","schema":{"type":"string","maxLength":60}},{"name":"groupId","in":"query","required":false,"description":"Only items in this group id.","schema":{"type":"string","maxLength":60}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"project":{"type":"object","properties":{"id":{"type":"string","description":"Project (board) id."},"name":{"type":"string","description":"Board name (\"\" if unset)."},"key":{"type":"string","description":"Short key used in item refs, e.g. \"PROJ\" → PROJ-12."},"color":{"type":"string","description":"Board colour, hex or \"\"."},"itemCount":{"type":"integer","description":"Number of items on the board."},"groups":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Group id."},"name":{"type":"string","description":"Group name."}},"additionalProperties":true,"required":["id"]},"description":"Row groups (sections) of the board."},"columns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Column id (accepted in create/update values)."},"title":{"type":"string","description":"Column title (also accepted in values)."},"type":{"type":"string","description":"Column type, e.g. status, people, date, text, number."}},"additionalProperties":true,"required":["id"]},"description":"Board columns; values are keyed by column title in item.values."},"statuses":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Status label name."},"done":{"type":"boolean","description":"true when this status means completed."},"cancelled":{"type":"boolean","description":"true when this status means cancelled."}},"additionalProperties":true,"required":["name","done","cancelled"]},"description":"Labels of the status column; use these names for item status."},"visibility":{"type":"string","description":"Board visibility, \"shared\" by default."},"owner":{"type":"string","description":"Owner email (\"\" if unknown)."}},"additionalProperties":true,"required":["id","name","key","color","itemCount","groups","columns","statuses","visibility","owner"],"description":"A project board (its metadata, not its items)."},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Item id."},"ref":{"type":"string","description":"Human ref \"<KEY>-<num>\", e.g. PROJ-12."},"projectId":{"type":"string","description":"Board id the item belongs to."},"projectName":{"type":"string","description":"Board name."},"title":{"type":"string","description":"Item title."},"status":{"type":"string","description":"Status label name (\"\" if none)."},"priority":{"type":"string","description":"Urgent | High | Medium | Low | None."},"assignees":{"type":"array","items":{"type":"string","description":"Assignee."},"description":"Assignee emails/names."},"dueDate":{"type":"string","description":"Due date YYYY-MM-DD or \"\"."},"groupId":{"type":"string","description":"Group id (\"\" if none)."},"group":{"type":"string","description":"Group name (\"\" if none)."},"labels":{"type":"array","items":{"description":"Label."},"description":"Item labels."},"values":{"type":"object","additionalProperties":true,"description":"Non-empty column values keyed by column title (or id when untitled)."},"comments":{"type":"integer","description":"Number of comments."},"subItems":{"type":"integer","description":"Number of sub-items."},"createdAt":{"type":"string","description":"ISO 8601 creation time or \"\"."}},"additionalProperties":true,"required":["id","ref","projectId","projectName","title","status","priority","assignees","dueDate","groupId","group","labels","values","comments","subItems","createdAt"],"description":"A project item (issue/task) on a board."},"description":"Items on the board (filtered by status/groupId)."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"Current page, 1-based."},"pageSize":{"type":"integer","description":"Rows per page after clamping."},"total":{"type":"integer","description":"Total rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"true when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the list (lib/mcp/schema.js paginate)."}},"additionalProperties":true,"required":["ok","requestId","project","items","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/projects/items":{"get":{"operationId":"search_project_items","summary":"Search items across every visible board by text (title, ref like CAMP-12, or any column value), status or assignee","description":"Search items across every visible board by text (title, ref like CAMP-12, or any column value), status or assignee. Use it for \"what is Dana working on\", \"everything still In Progress\", \"find the item about X\".\n\nRequired scope: `projects.read`. Risk level: `read`.","tags":["projects"],"security":[{"bearerAuth":["projects.read"]}],"parameters":[{"name":"query","in":"query","required":false,"description":"Free text or an item ref (KEY-number).","schema":{"type":"string","maxLength":120}},{"name":"projectId","in":"query","required":false,"description":"Restrict to one board.","schema":{"type":"string","maxLength":60}},{"name":"status","in":"query","required":false,"description":"Exact status label.","schema":{"type":"string","maxLength":60}},{"name":"assignee","in":"query","required":false,"description":"Assignee email or name (substring).","schema":{"type":"string","maxLength":120}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Item id."},"ref":{"type":"string","description":"Human ref \"<KEY>-<num>\", e.g. PROJ-12."},"projectId":{"type":"string","description":"Board id the item belongs to."},"projectName":{"type":"string","description":"Board name."},"title":{"type":"string","description":"Item title."},"status":{"type":"string","description":"Status label name (\"\" if none)."},"priority":{"type":"string","description":"Urgent | High | Medium | Low | None."},"assignees":{"type":"array","items":{"type":"string","description":"Assignee."},"description":"Assignee emails/names."},"dueDate":{"type":"string","description":"Due date YYYY-MM-DD or \"\"."},"groupId":{"type":"string","description":"Group id (\"\" if none)."},"group":{"type":"string","description":"Group name (\"\" if none)."},"labels":{"type":"array","items":{"description":"Label."},"description":"Item labels."},"values":{"type":"object","additionalProperties":true,"description":"Non-empty column values keyed by column title (or id when untitled)."},"comments":{"type":"integer","description":"Number of comments."},"subItems":{"type":"integer","description":"Number of sub-items."},"createdAt":{"type":"string","description":"ISO 8601 creation time or \"\"."}},"additionalProperties":true,"required":["id","ref","projectId","projectName","title","status","priority","assignees","dueDate","groupId","group","labels","values","comments","subItems","createdAt"],"description":"A project item (issue/task) on a board."},"description":"Matching items across boards, newest first."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"Current page, 1-based."},"pageSize":{"type":"integer","description":"Rows per page after clamping."},"total":{"type":"integer","description":"Total rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"true when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the list (lib/mcp/schema.js paginate)."}},"additionalProperties":true,"required":["ok","requestId","items","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/projects/{projectId}/items":{"post":{"operationId":"create_project_item","summary":"Add an item to a board","description":"Add an item to a board. status must be one of the board's labels (see list_projects); group accepts a group id or name; values is an object keyed by column id or title (numbers, text, dropdown arrays, ratings…). Unknown statuses, groups or columns are rejected with the valid options — nothing is silently dropped.\n\nRequired scope: `projects.write`. Risk level: `write`.","tags":["projects"],"security":[{"bearerAuth":["projects.write"]}],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Board id.","schema":{"type":"string","maxLength":60}},{"name":"title","in":"query","required":true,"description":"Item title.","schema":{"type":"string","maxLength":300}},{"name":"description","in":"query","required":false,"description":"Longer description.","schema":{"type":"string","maxLength":5000}},{"name":"status","in":"query","required":false,"description":"Status label. Default: the board's first open status.","schema":{"type":"string","maxLength":60}},{"name":"priority","in":"query","required":false,"description":"Priority.","schema":{"type":"string","enum":["Urgent","High","Medium","Low","None"]}},{"name":"assignees","in":"query","required":false,"description":"Assignee emails.","schema":{"type":"array","maxItems":10,"items":{"type":"string"}}},{"name":"dueDate","in":"query","required":false,"description":"YYYY-MM-DD.","schema":{"type":"string","maxLength":10}},{"name":"group","in":"query","required":false,"description":"Group id or name. Default: the first group.","schema":{"type":"string","maxLength":60}},{"name":"values","in":"query","required":false,"description":"Custom column values keyed by column id or title.","schema":{"type":"string"}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"created":{"type":"boolean","description":"Always true on success."},"item":{"type":"object","properties":{"id":{"type":"string","description":"Item id."},"ref":{"type":"string","description":"Human ref \"<KEY>-<num>\", e.g. PROJ-12."},"projectId":{"type":"string","description":"Board id the item belongs to."},"projectName":{"type":"string","description":"Board name."},"title":{"type":"string","description":"Item title."},"status":{"type":"string","description":"Status label name (\"\" if none)."},"priority":{"type":"string","description":"Urgent | High | Medium | Low | None."},"assignees":{"type":"array","items":{"type":"string","description":"Assignee."},"description":"Assignee emails/names."},"dueDate":{"type":"string","description":"Due date YYYY-MM-DD or \"\"."},"groupId":{"type":"string","description":"Group id (\"\" if none)."},"group":{"type":"string","description":"Group name (\"\" if none)."},"labels":{"type":"array","items":{"description":"Label."},"description":"Item labels."},"values":{"type":"object","additionalProperties":true,"description":"Non-empty column values keyed by column title (or id when untitled)."},"comments":{"type":"integer","description":"Number of comments."},"subItems":{"type":"integer","description":"Number of sub-items."},"createdAt":{"type":"string","description":"ISO 8601 creation time or \"\"."}},"additionalProperties":true,"required":["id","ref","projectId","projectName","title","status","priority","assignees","dueDate","groupId","group","labels","values","comments","subItems","createdAt"],"description":"A project item (issue/task) on a board."},"targetType":{"type":"string","enum":["project_item"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"New item id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","created","item","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/projects/{projectId}/items/{itemId}/update":{"post":{"operationId":"update_project_item","summary":"Change an item: title, status, priority, assignees (full replacement), due date, group, column values (merged), or add a comment","description":"Change an item: title, status, priority, assignees (full replacement), due date, group, column values (merged), or add a comment. Only the fields you pass change; each change is logged in the item's activity. itemId accepts the item id or its ref (KEY-number).\n\nRequired scope: `projects.write`. Risk level: `write`.","tags":["projects"],"security":[{"bearerAuth":["projects.write"]}],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Board id.","schema":{"type":"string","maxLength":60}},{"name":"itemId","in":"path","required":true,"description":"Item id or ref.","schema":{"type":"string","maxLength":60}},{"name":"title","in":"query","required":false,"description":"New title.","schema":{"type":"string","maxLength":300}},{"name":"status","in":"query","required":false,"description":"New status label.","schema":{"type":"string","maxLength":60}},{"name":"priority","in":"query","required":false,"description":"New priority.","schema":{"type":"string","enum":["Urgent","High","Medium","Low","None"]}},{"name":"assignees","in":"query","required":false,"description":"FULL replacement assignee list ([] to unassign).","schema":{"type":"array","maxItems":10,"items":{"type":"string"}}},{"name":"dueDate","in":"query","required":false,"description":"YYYY-MM-DD, or \"\" to clear.","schema":{"type":"string","maxLength":10}},{"name":"group","in":"query","required":false,"description":"Move to this group (id or name).","schema":{"type":"string","maxLength":60}},{"name":"values","in":"query","required":false,"description":"Column values to merge, keyed by column id or title.","schema":{"type":"string"}},{"name":"comment","in":"query","required":false,"description":"Append a comment.","schema":{"type":"string","maxLength":4000}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"updated":{"type":"boolean","description":"Always true on success."},"changes":{"type":"array","items":{"type":"string","description":"Change, e.g. \"changed status to Done\"."},"description":"Human-readable list of what changed."},"item":{"type":"object","properties":{"id":{"type":"string","description":"Item id."},"ref":{"type":"string","description":"Human ref \"<KEY>-<num>\", e.g. PROJ-12."},"projectId":{"type":"string","description":"Board id the item belongs to."},"projectName":{"type":"string","description":"Board name."},"title":{"type":"string","description":"Item title."},"status":{"type":"string","description":"Status label name (\"\" if none)."},"priority":{"type":"string","description":"Urgent | High | Medium | Low | None."},"assignees":{"type":"array","items":{"type":"string","description":"Assignee."},"description":"Assignee emails/names."},"dueDate":{"type":"string","description":"Due date YYYY-MM-DD or \"\"."},"groupId":{"type":"string","description":"Group id (\"\" if none)."},"group":{"type":"string","description":"Group name (\"\" if none)."},"labels":{"type":"array","items":{"description":"Label."},"description":"Item labels."},"values":{"type":"object","additionalProperties":true,"description":"Non-empty column values keyed by column title (or id when untitled)."},"comments":{"type":"integer","description":"Number of comments."},"subItems":{"type":"integer","description":"Number of sub-items."},"createdAt":{"type":"string","description":"ISO 8601 creation time or \"\"."}},"additionalProperties":true,"required":["id","ref","projectId","projectName","title","status","priority","assignees","dueDate","groupId","group","labels","values","comments","subItems","createdAt"],"description":"A project item (issue/task) on a board."},"targetType":{"type":"string","enum":["project_item"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Item id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","updated","changes","item","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/projects/{projectId}/items/{itemId}/delete":{"post":{"operationId":"delete_project_item","summary":"Remove an item from a board (with its comments and sub-items)","description":"Remove an item from a board (with its comments and sub-items). PREVIEW FIRST: without confirm it shows the item that would be removed. The board keeps a restorable version snapshot in the app, but the item is gone from the board immediately.\n\nRequired scope: `records.delete`. Risk level: `high`.","tags":["records"],"security":[{"bearerAuth":["records.delete"]}],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Board id.","schema":{"type":"string","maxLength":60}},{"name":"itemId","in":"path","required":true,"description":"Item id.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"willDelete":{"type":"object","properties":{"id":{"type":"string","description":"Item id."},"ref":{"type":"string","description":"Human ref \"<KEY>-<num>\", e.g. PROJ-12."},"projectId":{"type":"string","description":"Board id the item belongs to."},"projectName":{"type":"string","description":"Board name."},"title":{"type":"string","description":"Item title."},"status":{"type":"string","description":"Status label name (\"\" if none)."},"priority":{"type":"string","description":"Urgent | High | Medium | Low | None."},"assignees":{"type":"array","items":{"type":"string","description":"Assignee."},"description":"Assignee emails/names."},"dueDate":{"type":"string","description":"Due date YYYY-MM-DD or \"\"."},"groupId":{"type":"string","description":"Group id (\"\" if none)."},"group":{"type":"string","description":"Group name (\"\" if none)."},"labels":{"type":"array","items":{"description":"Label."},"description":"Item labels."},"values":{"type":"object","additionalProperties":true,"description":"Non-empty column values keyed by column title (or id when untitled)."},"comments":{"type":"integer","description":"Number of comments."},"subItems":{"type":"integer","description":"Number of sub-items."},"createdAt":{"type":"string","description":"ISO 8601 creation time or \"\"."}},"additionalProperties":true,"required":["id","ref","projectId","projectName","title","status","priority","assignees","dueDate","groupId","group","labels","values","comments","subItems","createdAt"],"description":"Preview only: the item that would be removed."},"warning":{"type":"string","description":"Preview only: consequences of confirming."},"deleted":{"type":"boolean","description":"Run only: true on success."},"itemId":{"type":"string","description":"Run only: removed item id."},"targetType":{"type":"string","enum":["project_item"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Item id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/landing-pages":{"get":{"operationId":"list_landing_pages","summary":"The workspace's landing pages with performance: views, clicks, leads captured, conversion rate, average time on page and 14-day daily views","description":"The workspace's landing pages with performance: views, clicks, leads captured, conversion rate, average time on page and 14-day daily views. Leads captured by a page are also searchable with search_leads (source landing_page).\n\nRequired scope: `pages.read`. Risk level: `read`.","tags":["pages"],"security":[{"bearerAuth":["pages.read"]}],"parameters":[{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"pages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Landing page id."},"name":{"type":"string","description":"Page name (falls back to title)."},"slug":{"type":"string","description":"URL slug or \"\"."},"url":{"type":"string","description":"Public URL or \"\"."},"published":{"type":"boolean","description":"false only when explicitly unpublished."},"listId":{"type":"string","description":"Landing-page list id or \"\"."},"createdAt":{"description":"Creation time: ISO 8601, epoch ms or \"\"."},"views":{"type":"number","description":"Page views."},"clicks":{"type":"number","description":"Clicks."},"leads":{"type":"number","description":"Leads captured."},"conversionRate":{"type":"number","description":"leads / views as a percentage, 1 decimal."},"avgDwellSeconds":{"type":"number","description":"Average time on page, seconds, 1 decimal."},"dailyViews":{"description":"Daily view series when the stats endpoint provides one."}},"additionalProperties":true,"required":["id","name","slug","url","published","listId","createdAt","views","clicks","leads","conversionRate","avgDwellSeconds"]},"description":"Landing pages with traffic stats, most viewed first."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"Current page, 1-based."},"pageSize":{"type":"integer","description":"Rows per page after clamping."},"total":{"type":"integer","description":"Total rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"true when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the list (lib/mcp/schema.js paginate)."}},"additionalProperties":true,"required":["ok","requestId","pages","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/email-campaigns":{"get":{"operationId":"list_email_campaigns","summary":"Sent email campaigns with results: sent, unique opens and open rate, unique clicks and click rate, unsubscribes, bounces, complaints, attributed orders/revenue, A/B winner","description":"Sent email campaigns with results: sent, unique opens and open rate, unique clicks and click rate, unsubscribes, bounces, complaints, attributed orders/revenue, A/B winner. Newest first. Use it for \"how did last week's newsletter do\".\n\nRequired scope: `reports.read`. Risk level: `read`.","tags":["reports"],"security":[{"bearerAuth":["reports.read"]}],"parameters":[{"name":"query","in":"query","required":false,"description":"Filter by campaign name or subject.","schema":{"type":"string","maxLength":120}},{"name":"includeArchived","in":"query","required":false,"description":"Include archived campaigns.","schema":{"type":"boolean","default":false}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"campaigns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Campaign id."},"name":{"type":"string","description":"Campaign name."},"subject":{"type":"string","description":"Email subject."},"from":{"type":"string","description":"Sender address."},"audience":{"description":"Audience / segment the campaign went to."},"sentAt":{"description":"Send time (epoch ms or ISO 8601)."},"sent":{"type":"number","description":"Recipients."},"opens":{"type":"number","description":"Unique opens."},"openRate":{"type":"number","description":"Unique opens / sent, percent, 1 decimal."},"clicks":{"type":"number","description":"Unique clicks."},"clickRate":{"type":"number","description":"Unique clicks / sent, percent, 1 decimal."},"unsubscribes":{"type":"number","description":"Unsubscribes."},"bounces":{"type":"number","description":"Bounces."},"complaints":{"type":"number","description":"Spam complaints."},"orders":{"type":"number","description":"Attributed orders."},"revenue":{"type":"number","description":"Attributed revenue, account currency (absent when 0)."},"abWinner":{"description":"Winning A/B variant when the campaign was a test."},"archived":{"type":"boolean","description":"true when archived."}},"additionalProperties":true,"required":["openRate","clickRate","orders","archived"]},"description":"Sent email campaigns with delivery stats."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"Current page, 1-based."},"pageSize":{"type":"integer","description":"Rows per page after clamping."},"total":{"type":"integer","description":"Total rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"true when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the list (lib/mcp/schema.js paginate)."}},"additionalProperties":true,"required":["ok","requestId","campaigns","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/sms-campaigns":{"get":{"operationId":"list_sms_campaigns","summary":"Sent SMS campaigns with results: sent, delivered and delivery rate, failed, link clicks and click rate, unsubscribes, attributed orders/revenue","description":"Sent SMS campaigns with results: sent, delivered and delivery rate, failed, link clicks and click rate, unsubscribes, attributed orders/revenue. Newest first.\n\nRequired scope: `reports.read`. Risk level: `read`.","tags":["reports"],"security":[{"bearerAuth":["reports.read"]}],"parameters":[{"name":"query","in":"query","required":false,"description":"Filter by campaign name or message text.","schema":{"type":"string","maxLength":120}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"campaigns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Campaign id."},"name":{"type":"string","description":"Campaign name."},"sender":{"type":"string","description":"Sender id."},"audience":{"description":"Audience / segment the campaign went to."},"sentAt":{"description":"Send time (epoch ms or ISO 8601)."},"message":{"type":"string","description":"Message text, first 300 chars."},"sent":{"type":"number","description":"Recipients."},"delivered":{"type":"number","description":"Delivered."},"deliveryRate":{"type":"number","description":"delivered / sent, percent, 1 decimal."},"failed":{"type":"number","description":"Failed deliveries."},"clicks":{"type":"number","description":"Link clicks."},"clickRate":{"type":"number","description":"clicks / delivered, percent, 1 decimal."},"unsubscribes":{"type":"number","description":"Unsubscribes."},"orders":{"type":"number","description":"Attributed orders."},"revenue":{"type":"number","description":"Attributed revenue, account currency (absent when 0)."}},"additionalProperties":true,"required":["message","deliveryRate","clickRate","orders"]},"description":"Sent SMS campaigns with delivery stats, newest first."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"Current page, 1-based."},"pageSize":{"type":"integer","description":"Rows per page after clamping."},"total":{"type":"integer","description":"Total rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"true when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the list (lib/mcp/schema.js paginate)."}},"additionalProperties":true,"required":["ok","requestId","campaigns","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/landing-pages/{id}":{"get":{"operationId":"get_landing_page","summary":"One landing page with its settings (URL, list, SEO, expiry) and its HTML (capped; pass maxHtmlChars for more)","description":"One landing page with its settings (URL, list, SEO, expiry) and its HTML (capped; pass maxHtmlChars for more). Read it before editing so replaceText edits match the real markup.\n\nRequired scope: `pages.read`. Risk level: `read`.","tags":["pages"],"security":[{"bearerAuth":["pages.read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Page id from list_landing_pages.","schema":{"type":"string","maxLength":60}},{"name":"maxHtmlChars","in":"query","required":false,"description":"How much HTML to return (1000-60000, default 20000).","schema":{"type":"integer","minimum":1000,"maximum":60000}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"page":{"type":"object","properties":{"id":{"type":"string","description":"Landing page id."},"name":{"type":"string","description":"Internal page name."},"title":{"type":"string","description":"Page <title>."},"description":{"type":"string","description":"Meta description."},"pageType":{"type":"string","description":"Page type, e.g. minisite."},"kind":{"type":"string","description":"html (code page) or canvas."},"slug":{"type":"string","description":"URL slug (\"\" when served by id)."},"url":{"type":"string","description":"Public URL https://app.fortvision.com/lp/{slug|id}."},"domain":{"type":"string","description":"Custom domain or \"\"."},"listId":{"type":"string","description":"Landing-page list id or \"\"."},"listName":{"type":"string","description":"Landing-page list name or \"\"."},"campaignName":{"type":"string","description":"Linked campaign name or \"\"."},"noindex":{"type":"boolean","description":"true when robots noindex is set."},"redirectUrl":{"type":"string","description":"Post-submit redirect URL or \"\"."},"expiresAt":{"type":"string","description":"Expiry date/time or \"\"."},"leadCount":{"type":"integer","description":"Leads captured by the page."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."},"updatedAt":{"type":"string","description":"ISO 8601 or \"\"."}},"additionalProperties":true,"required":["id","name","title","description","pageType","kind","slug","url","domain","listId","listName","campaignName","noindex","redirectUrl","expiresAt","leadCount","createdAt","updatedAt"],"description":"Landing page metadata (no HTML)."},"htmlLength":{"type":"integer","description":"Full HTML length in chars."},"htmlTruncated":{"type":"boolean","description":"true when html was cut at maxHtmlChars."},"html":{"type":"string","description":"Page HTML, up to maxHtmlChars."},"canvasDesign":{"type":"boolean","description":"true when the page is a canvas design (HTML is generated)."}},"additionalProperties":true,"required":["ok","requestId","page","htmlLength","htmlTruncated","html","canvasDesign"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/landing-pages/generate":{"post":{"operationId":"generate_landing_page","summary":"Create a new landing page with the platform's AI page generator from a brief (prompt and/or title, description, paragraphs, image URLs), save it and return its URL","description":"Create a new landing page with the platform's AI page generator from a brief (prompt and/or title, description, paragraphs, image URLs), save it and return its URL. Takes 30-90 seconds. The page is live at its URL immediately but nothing is promoted; it can be edited with update_landing_page or removed with delete_landing_page. Leads submitted on it land in the CRM (and in listId if given).\n\nRequired scope: `pages.write`. Risk level: `write`.","tags":["pages"],"security":[{"bearerAuth":["pages.write"]}],"parameters":[{"name":"name","in":"query","required":true,"description":"Internal page name.","schema":{"type":"string","maxLength":120}},{"name":"prompt","in":"query","required":false,"description":"Brief for the generator: business, offer, audience, tone, sections wanted.","schema":{"type":"string","maxLength":8000}},{"name":"title","in":"query","required":false,"description":"Hero title.","schema":{"type":"string","maxLength":300}},{"name":"description","in":"query","required":false,"description":"Sub-headline / summary.","schema":{"type":"string","maxLength":2000}},{"name":"paragraphs","in":"query","required":false,"description":"Body paragraphs to include.","schema":{"type":"array","maxItems":40,"items":{"type":"string"}}},{"name":"imageUrls","in":"query","required":false,"description":"Image URLs the page may use.","schema":{"type":"array","maxItems":24,"items":{"type":"string"}}},{"name":"pageType","in":"query","required":false,"description":"Layout family.","schema":{"type":"string","enum":["minisite","landing","form"]}},{"name":"listId","in":"query","required":false,"description":"Landing-page list to route leads into (from list_landing_page_lists).","schema":{"type":"string","maxLength":60}},{"name":"listName","in":"query","required":false,"description":"Display name of that list.","schema":{"type":"string","maxLength":80}},{"name":"slug","in":"query","required":false,"description":"Custom URL slug (a-z, 0-9, dashes; must be free).","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"created":{"type":"boolean","description":"Always true on success."},"page":{"type":"object","properties":{"id":{"type":"string","description":"Landing page id."},"name":{"type":"string","description":"Page name."},"title":{"type":"string","description":"Page <title>."},"description":{"type":"string","description":"Meta description."},"pageType":{"type":"string","description":"Page type, e.g. minisite."},"kind":{"type":"string","description":"html (code page) or canvas."},"slug":{"type":"string","description":"URL slug (\"\" when served by id)."},"url":{"type":"string","description":"Public URL https://app.fortvision.com/lp/{slug|id}."},"domain":{"type":"string","description":"Custom domain or \"\"."},"listId":{"type":"string","description":"Landing-page list id or \"\"."},"listName":{"type":"string","description":"Landing-page list name or \"\"."},"campaignName":{"type":"string","description":"Linked campaign name or \"\"."},"noindex":{"type":"boolean","description":"true when robots noindex is set."},"redirectUrl":{"type":"string","description":"Post-submit redirect URL or \"\"."},"expiresAt":{"type":"string","description":"Expiry date/time or \"\"."},"leadCount":{"type":"integer","description":"Leads captured by the page."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."},"updatedAt":{"type":"string","description":"ISO 8601 or \"\"."}},"additionalProperties":true,"required":["id","name","title","description","pageType","kind","slug","url","domain","listId","listName","campaignName","noindex","redirectUrl","expiresAt","leadCount","createdAt","updatedAt"],"description":"The new page; full metadata when it could be re-read, else just id and name."},"model":{"type":"string","description":"AI model that generated the page (\"\" if unknown)."},"targetType":{"type":"string","enum":["landing_page"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"New page id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","created","page","model","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/landing-pages/{id}/update":{"post":{"operationId":"update_landing_page","summary":"Edit a landing page: settings (name, slug, list, SEO title/og image, noindex, redirect, expiry) and/or content","description":"Edit a landing page: settings (name, slug, list, SEO title/og image, noindex, redirect, expiry) and/or content. Content edits: replaceText = exact find→replace pairs applied to the page HTML (a find string that matches nowhere is rejected, so a typo cannot silently do nothing), or html = full replacement. Read the page first with get_landing_page.\n\nRequired scope: `pages.write`. Risk level: `write`.","tags":["pages"],"security":[{"bearerAuth":["pages.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Page id.","schema":{"type":"string","maxLength":60}},{"name":"name","in":"query","required":false,"description":"Internal name.","schema":{"type":"string","maxLength":120}},{"name":"title","in":"query","required":false,"description":"SEO/hero title.","schema":{"type":"string","maxLength":300}},{"name":"description","in":"query","required":false,"description":"Meta description.","schema":{"type":"string","maxLength":2000}},{"name":"slug","in":"query","required":false,"description":"Custom URL slug, or \"\" to clear.","schema":{"type":"string","maxLength":60}},{"name":"listId","in":"query","required":false,"description":"Landing-page list id for new leads, or \"\" to clear.","schema":{"type":"string","maxLength":60}},{"name":"listName","in":"query","required":false,"description":"Display name of that list.","schema":{"type":"string","maxLength":80}},{"name":"ogTitle","in":"query","required":false,"description":"Open Graph title.","schema":{"type":"string","maxLength":200}},{"name":"ogImage","in":"query","required":false,"description":"Open Graph image URL.","schema":{"type":"string","maxLength":600}},{"name":"noindex","in":"query","required":false,"description":"Hide from search engines.","schema":{"type":"boolean"}},{"name":"redirectUrl","in":"query","required":false,"description":"Redirect after form submit.","schema":{"type":"string","maxLength":600}},{"name":"expiresAt","in":"query","required":false,"description":"ISO date-time after which the page shows expiredMsg.","schema":{"type":"string","maxLength":40}},{"name":"expiredMsg","in":"query","required":false,"description":"Message shown after expiry.","schema":{"type":"string","maxLength":400}},{"name":"replaceText","in":"query","required":false,"description":"Exact text edits: [{find, replace}] applied to the HTML in order.","schema":{"type":"array","maxItems":40,"items":{"type":"object"}}},{"name":"html","in":"query","required":false,"description":"FULL replacement HTML (use only when replaceText is not enough).","schema":{"type":"string","maxLength":400000}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"updated":{"type":"boolean","description":"Always true on success."},"page":{"type":"object","properties":{"id":{"type":"string","description":"Landing page id."},"name":{"type":"string","description":"Internal page name."},"title":{"type":"string","description":"Page <title>."},"description":{"type":"string","description":"Meta description."},"pageType":{"type":"string","description":"Page type, e.g. minisite."},"kind":{"type":"string","description":"html (code page) or canvas."},"slug":{"type":"string","description":"URL slug (\"\" when served by id)."},"url":{"type":"string","description":"Public URL https://app.fortvision.com/lp/{slug|id}."},"domain":{"type":"string","description":"Custom domain or \"\"."},"listId":{"type":"string","description":"Landing-page list id or \"\"."},"listName":{"type":"string","description":"Landing-page list name or \"\"."},"campaignName":{"type":"string","description":"Linked campaign name or \"\"."},"noindex":{"type":"boolean","description":"true when robots noindex is set."},"redirectUrl":{"type":"string","description":"Post-submit redirect URL or \"\"."},"expiresAt":{"type":"string","description":"Expiry date/time or \"\"."},"leadCount":{"type":"integer","description":"Leads captured by the page."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."},"updatedAt":{"type":"string","description":"ISO 8601 or \"\"."}},"additionalProperties":true,"required":["id","name","title","description","pageType","kind","slug","url","domain","listId","listName","campaignName","noindex","redirectUrl","expiresAt","leadCount","createdAt","updatedAt"],"description":"Landing page metadata (no HTML)."},"textEdits":{"type":"array","items":{"type":"object","properties":{"find":{"type":"string","description":"Search text (first 80 chars)."},"matches":{"type":"integer","description":"Occurrences replaced."}},"additionalProperties":true,"required":["find","matches"]},"description":"replaceText edits that were applied."},"htmlReplaced":{"type":"boolean","description":"true when the whole HTML was replaced."},"targetType":{"type":"string","enum":["landing_page"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Page id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","updated","page","textEdits","htmlReplaced","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/landing-pages/{id}/delete":{"post":{"operationId":"delete_landing_page","summary":"Take a landing page down (its URL stops serving)","description":"Take a landing page down (its URL stops serving). PREVIEW FIRST: without confirm it shows the page and how many leads it captured (they stay in the CRM).\n\nRequired scope: `records.delete`. Risk level: `high`.","tags":["records"],"security":[{"bearerAuth":["records.delete"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Page id.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"willDelete":{"type":"object","properties":{"id":{"type":"string","description":"Landing page id."},"name":{"type":"string","description":"Internal page name."},"title":{"type":"string","description":"Page <title>."},"description":{"type":"string","description":"Meta description."},"pageType":{"type":"string","description":"Page type, e.g. minisite."},"kind":{"type":"string","description":"html (code page) or canvas."},"slug":{"type":"string","description":"URL slug (\"\" when served by id)."},"url":{"type":"string","description":"Public URL https://app.fortvision.com/lp/{slug|id}."},"domain":{"type":"string","description":"Custom domain or \"\"."},"listId":{"type":"string","description":"Landing-page list id or \"\"."},"listName":{"type":"string","description":"Landing-page list name or \"\"."},"campaignName":{"type":"string","description":"Linked campaign name or \"\"."},"noindex":{"type":"boolean","description":"true when robots noindex is set."},"redirectUrl":{"type":"string","description":"Post-submit redirect URL or \"\"."},"expiresAt":{"type":"string","description":"Expiry date/time or \"\"."},"leadCount":{"type":"integer","description":"Leads captured by the page."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."},"updatedAt":{"type":"string","description":"ISO 8601 or \"\"."}},"additionalProperties":true,"required":["id","name","title","description","pageType","kind","slug","url","domain","listId","listName","campaignName","noindex","redirectUrl","expiresAt","leadCount","createdAt","updatedAt"],"description":"Preview only: the page that would be deleted."},"warning":{"type":"string","description":"Preview only: consequences of confirming."},"deleted":{"type":"boolean","description":"Run only: true on success."},"id":{"type":"string","description":"Run only: deleted page id."},"targetType":{"type":"string","enum":["landing_page"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Page id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/landing-pages/lists":{"get":{"operationId":"list_landing_page_lists","summary":"The landing-page lead lists (a page routes its leads into one), with lead counts","description":"The landing-page lead lists (a page routes its leads into one), with lead counts.\n\nRequired scope: `pages.read`. Risk level: `read`.","tags":["pages"],"security":[{"bearerAuth":["pages.read"]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"lists":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"List id (list_…)."},"name":{"type":"string","description":"List name."},"count":{"type":"integer","description":"Pages in the list."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."}},"additionalProperties":true,"required":["id","name","count","createdAt"]},"description":"Landing-page lists (folders)."}},"additionalProperties":true,"required":["ok","requestId","lists"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"create_landing_page_list","summary":"Create a landing-page lead list (returns the existing one if the name already exists)","description":"Create a landing-page lead list (returns the existing one if the name already exists).\n\nRequired scope: `pages.write`. Risk level: `write`.","tags":["pages"],"security":[{"bearerAuth":["pages.write"]}],"parameters":[{"name":"name","in":"query","required":true,"description":"List name.","schema":{"type":"string","maxLength":80}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"created":{"type":"boolean","description":"Always true (an existing list with the same name is returned instead)."},"list":{"type":"object","properties":{"id":{"type":"string","description":"List id (list_…)."},"name":{"type":"string","description":"List name."},"createdAt":{"type":"string","description":"ISO 8601."},"count":{"type":"integer","description":"Pages in the list."}},"additionalProperties":true,"required":["id","name","createdAt","count"],"description":"The list record."},"targetType":{"type":"string","enum":["lp_list"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"List id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","created","list","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/social/posts":{"get":{"operationId":"list_social_posts","summary":"Posts in the social calendar (the currently focused page/client): status (draft / pending / scheduled / published / rejected), copy, channels, schedule time, image, and real stats for published ones","description":"Posts in the social calendar (the currently focused page/client): status (draft / pending / scheduled / published / rejected), copy, channels, schedule time, image, and real stats for published ones.\n\nRequired scope: `social.read`. Risk level: `read`.","tags":["social"],"security":[{"bearerAuth":["social.read"]}],"parameters":[{"name":"status","in":"query","required":false,"description":"Filter by status.","schema":{"type":"string","enum":["draft","pending","scheduled","published","rejected"]}},{"name":"query","in":"query","required":false,"description":"Text in title, headline or copy.","schema":{"type":"string","maxLength":120}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"posts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Post id."},"status":{"type":"string","description":"draft | pending | scheduled | published | rejected."},"title":{"type":"string","description":"Internal title."},"headline":{"type":"string","description":"Headline."},"copy":{"type":"string","description":"Post text (max 2200 chars)."},"cta":{"type":"string","description":"Call to action."},"hashtags":{"type":"array","items":{"type":"string","description":"Hashtag."},"description":"Hashtags."},"channels":{"type":"array","items":{"type":"string","description":"facebook | instagram | linkedin | groups | tiktok."},"description":"Target channels."},"lang":{"type":"string","description":"Language code, e.g. en, he."},"format":{"type":"string","description":"image | video | carousel | text."},"ptype":{"type":"string","description":"post | story | reel."},"label":{"type":"string","description":"Variant label (safe/creative/rtm) or \"\"."},"image":{"type":"string","description":"Image URL or \"\"."},"video":{"type":"string","description":"Video URL or \"\"."},"link":{"type":"string","description":"Link URL or \"\"."},"pageName":{"type":"string","description":"Connected page name or \"\"."},"scheduledAt":{"type":"string","description":"ISO 8601 or \"\"."},"publishedAt":{"type":"string","description":"ISO 8601 or \"\"."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."},"updatedAt":{"type":"string","description":"ISO 8601 or \"\"."},"clientApproved":{"type":"boolean","description":"Client approval flag."},"stats":{"type":"object","properties":{"reach":{"type":"number","description":"Reach."},"impressions":{"type":"number","description":"Impressions."},"engagement":{"type":"number","description":"Engagement count."},"clicks":{"type":"number","description":"Clicks."},"likes":{"type":"number","description":"Likes."},"comments":{"type":"number","description":"Comments."}},"additionalProperties":true,"description":"Live network stats when available."},"leads":{"type":"number","description":"Leads attributed to the post."}},"additionalProperties":true,"required":["id","status","title","headline","copy","cta","hashtags","channels","lang","format","ptype","label","image","video","link","pageName","scheduledAt","publishedAt","createdAt","updatedAt","clientApproved","leads"],"description":"A social calendar post."},"description":"Calendar posts (filtered by status/query)."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"Current page, 1-based."},"pageSize":{"type":"integer","description":"Rows per page after clamping."},"total":{"type":"integer","description":"Total rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"true when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the list (lib/mcp/schema.js paginate)."}},"additionalProperties":true,"required":["ok","requestId","posts","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"create_social_post","summary":"Save a post to the calendar as a DRAFT (or pending client approval)","description":"Save a post to the calendar as a DRAFT (or pending client approval). Never publishes: scheduling and publishing are separate confirm-gated tools.\n\nRequired scope: `social.write`. Risk level: `write`.","tags":["social"],"security":[{"bearerAuth":["social.write"]}],"parameters":[{"name":"copy","in":"query","required":true,"description":"Post text.","schema":{"type":"string","maxLength":2200}},{"name":"title","in":"query","required":false,"description":"Internal title.","schema":{"type":"string","maxLength":200}},{"name":"headline","in":"query","required":false,"description":"Headline / first line.","schema":{"type":"string","maxLength":200}},{"name":"cta","in":"query","required":false,"description":"Call to action.","schema":{"type":"string","maxLength":60}},{"name":"hashtags","in":"query","required":false,"description":"Up to 8 hashtags.","schema":{"type":"array","maxItems":8,"items":{"type":"string"}}},{"name":"channels","in":"query","required":false,"description":"facebook / instagram / linkedin / groups / tiktok.","schema":{"type":"array","maxItems":5,"items":{"type":"string"}}},{"name":"lang","in":"query","required":false,"description":"Language code (default en).","schema":{"type":"string","maxLength":5}},{"name":"format","in":"query","required":false,"description":"image / video / carousel / text.","schema":{"type":"string","maxLength":20}},{"name":"ptype","in":"query","required":false,"description":"Post type.","schema":{"type":"string","enum":["post","story","reel"]}},{"name":"label","in":"query","required":false,"description":"Content label.","schema":{"type":"string","enum":["promo","edu","engage","bts","seasonal","other"]}},{"name":"image","in":"query","required":false,"description":"Hosted image URL.","schema":{"type":"string","maxLength":500}},{"name":"video","in":"query","required":false,"description":"Hosted video URL (reels).","schema":{"type":"string","maxLength":500}},{"name":"link","in":"query","required":false,"description":"Link to include.","schema":{"type":"string","maxLength":500}},{"name":"scheduledAt","in":"query","required":false,"description":"Intended time (ISO 8601) — stored only; schedule_social_post arms it.","schema":{"type":"string","maxLength":40}},{"name":"status","in":"query","required":false,"description":"draft (default) or pending (awaiting client approval).","schema":{"type":"string","enum":["draft","pending"]}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"created":{"type":"boolean","description":"Always true on success."},"post":{"type":"object","properties":{"id":{"type":"string","description":"Post id."},"status":{"type":"string","description":"draft | pending | scheduled | published | rejected."},"title":{"type":"string","description":"Internal title."},"headline":{"type":"string","description":"Headline."},"copy":{"type":"string","description":"Post text (max 2200 chars)."},"cta":{"type":"string","description":"Call to action."},"hashtags":{"type":"array","items":{"type":"string","description":"Hashtag."},"description":"Hashtags."},"channels":{"type":"array","items":{"type":"string","description":"facebook | instagram | linkedin | groups | tiktok."},"description":"Target channels."},"lang":{"type":"string","description":"Language code, e.g. en, he."},"format":{"type":"string","description":"image | video | carousel | text."},"ptype":{"type":"string","description":"post | story | reel."},"label":{"type":"string","description":"Variant label (safe/creative/rtm) or \"\"."},"image":{"type":"string","description":"Image URL or \"\"."},"video":{"type":"string","description":"Video URL or \"\"."},"link":{"type":"string","description":"Link URL or \"\"."},"pageName":{"type":"string","description":"Connected page name or \"\"."},"scheduledAt":{"type":"string","description":"ISO 8601 or \"\"."},"publishedAt":{"type":"string","description":"ISO 8601 or \"\"."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."},"updatedAt":{"type":"string","description":"ISO 8601 or \"\"."},"clientApproved":{"type":"boolean","description":"Client approval flag."},"stats":{"type":"object","properties":{"reach":{"type":"number","description":"Reach."},"impressions":{"type":"number","description":"Impressions."},"engagement":{"type":"number","description":"Engagement count."},"clicks":{"type":"number","description":"Clicks."},"likes":{"type":"number","description":"Likes."},"comments":{"type":"number","description":"Comments."}},"additionalProperties":true,"description":"Live network stats when available."},"leads":{"type":"number","description":"Leads attributed to the post."}},"additionalProperties":true,"required":["id","status","title","headline","copy","cta","hashtags","channels","lang","format","ptype","label","image","video","link","pageName","scheduledAt","publishedAt","createdAt","updatedAt","clientApproved","leads"],"description":"A social calendar post."},"approvalGated":{"type":"boolean","description":"true when client approval is required before it can go live."},"targetType":{"type":"string","enum":["social_post"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"New post id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","created","post","approvalGated","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/social/performance":{"get":{"operationId":"get_social_performance","summary":"Aggregate social performance of published posts (reach, impressions, engagement, clicks, leads) with the best channel / format / language and top posts","description":"Aggregate social performance of published posts (reach, impressions, engagement, clicks, leads) with the best channel / format / language and top posts. Refreshes stale insights first, so it can take ~10s.\n\nRequired scope: `social.read`. Risk level: `read`.","tags":["social"],"security":[{"bearerAuth":["social.read"]}],"parameters":[{"name":"lang","in":"query","required":false,"description":"Language for the narrative fields.","schema":{"type":"string","enum":["en","he"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"metrics":{"type":"object","properties":{"published":{"type":"integer","description":"Published posts."},"reach":{"type":"number","description":"Reach."},"engagement":{"type":"number","description":"Engagement."},"clicks":{"type":"number","description":"Clicks."},"likes":{"type":"number","description":"Likes."},"comments":{"type":"number","description":"Comments."},"leads":{"type":"number","description":"Leads attributed to posts."}},"additionalProperties":true,"required":["published","reach","engagement","clicks","likes","comments","leads"],"description":"Totals over published posts (estimates when seeded=true)."},"bestChannel":{"type":"string","description":"Top channel by engagement."},"bestLang":{"type":"string","description":"Top language by engagement."},"bestFormat":{"type":"string","description":"Top format by engagement."},"insights":{"type":"array","items":{"type":"string","description":"Insight."},"description":"Short insight sentences in the requested language."},"seeded":{"type":"boolean","description":"true when no real stats exist yet and metrics are estimates."},"recommendation":{"type":"string","description":"One-line recommendation."},"posts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Post id (sc_… or fb_… for posts imported from the page)."},"text":{"type":"string","description":"Post text excerpt (up to 160 chars, whitespace collapsed)."},"image":{"type":"string","description":"Image URL or empty."},"channels":{"type":"array","items":{"type":"string","description":"facebook / instagram / linkedin / groups / tiktok."},"description":"Channels it was published to."},"pageName":{"type":"string","description":"Page it was published from."},"format":{"type":"string","description":"image / video / carousel / text."},"publishedAt":{"type":"string","description":"ISO 8601 publish time, or empty."},"url":{"type":"string","description":"Live post URL when known."},"statsAt":{"type":"string","description":"ISO 8601 time the stats were last refreshed, or empty."},"metrics":{"type":"object","properties":{"reach":{"type":"number","description":"Reach."},"impressions":{"type":"number","description":"Impressions."},"engagement":{"type":"number","description":"Engagement (reactions + comments + shares + clicks)."},"clicks":{"type":"number","description":"Clicks."},"likes":{"type":"number","description":"Likes / reactions."},"comments":{"type":"number","description":"Comments."},"leads":{"type":"number","description":"Leads attributed to this post."}},"additionalProperties":true,"required":["reach","impressions","engagement","clicks","likes","comments","leads"],"description":"Live metrics for this post."}},"additionalProperties":true,"required":["id","text","image","channels","pageName","format","publishedAt","url","statsAt","metrics"],"description":"A published post with its live stats (newest first)."},"description":"Up to 20 published posts, newest first."},"tiktokAccount":{"type":["object","null"],"properties":{"username":{"type":"string","description":"Handle."},"displayName":{"type":"string","description":"Display name."},"avatar":{"type":"string","description":"Profile image URL."},"followers":{"type":"number","description":"Followers."},"totalLikes":{"type":"number","description":"Total likes."},"videos":{"type":"number","description":"Video count."},"views7d":{"type":"number","description":"Video views, last 7 days."},"profileViews7d":{"type":"number","description":"Profile views, last 7 days."},"likes7d":{"type":"number","description":"Likes, last 7 days."},"comments7d":{"type":"number","description":"Comments, last 7 days."},"shares7d":{"type":"number","description":"Shares, last 7 days."},"newFollowers7d":{"type":"number","description":"New followers, last 7 days."}},"additionalProperties":true,"description":"TikTok account insights; null when not connected."}},"additionalProperties":true,"required":["ok","requestId","metrics","bestChannel","bestLang","bestFormat","insights","seeded","recommendation","posts","tiktokAccount"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/social/generate":{"post":{"operationId":"generate_social_posts","summary":"Ask the platform's social AI (brand-aware) for post ideas: topic/source, angle, audience, objective, tone, channels, format, languages","description":"Ask the platform's social AI (brand-aware) for post ideas: topic/source, angle, audience, objective, tone, channels, format, languages. Returns generated variants — nothing is saved until you call create_social_post with the one you want. Takes 20-60s.\n\nRequired scope: `social.write`. Risk level: `write`.","tags":["social"],"security":[{"bearerAuth":["social.write"]}],"parameters":[{"name":"topic","in":"query","required":false,"description":"What the post is about (a news item, product, event…).","schema":{"type":"string","maxLength":300}},{"name":"angle","in":"query","required":false,"description":"Angle or hook.","schema":{"type":"string","maxLength":300}},{"name":"audience","in":"query","required":false,"description":"Who it is for.","schema":{"type":"string","maxLength":300}},{"name":"focus","in":"query","required":false,"description":"Product/service to focus on.","schema":{"type":"string","maxLength":300}},{"name":"objective","in":"query","required":false,"description":"awareness / leads / engagement / sales.","schema":{"type":"string","maxLength":60}},{"name":"tone","in":"query","required":false,"description":"Tone of voice.","schema":{"type":"string","maxLength":60}},{"name":"channels","in":"query","required":false,"description":"Target channels.","schema":{"type":"array","maxItems":5,"items":{"type":"string"}}},{"name":"format","in":"query","required":false,"description":"image / video / carousel / text.","schema":{"type":"string","maxLength":20}},{"name":"langs","in":"query","required":false,"description":"Languages, e.g. [\"he\",\"en\"].","schema":{"type":"array","maxItems":4,"items":{"type":"string"}}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"ideas":{"type":"object","additionalProperties":true,"description":"Keyed by language code → { versions:[{id,label,copy,headline,cta,hashtags,bestTime,visual,channels}], qc?, error? }."},"historyId":{"type":"string","description":"Generation-history id when the result was saved."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","ideas"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/social/posts/{id}/update":{"post":{"operationId":"update_social_post","summary":"Edit a draft/pending/scheduled post (copy, headline, hashtags, channels, image, link, intended time…)","description":"Edit a draft/pending/scheduled post (copy, headline, hashtags, channels, image, link, intended time…). Only passed fields change; the previous content is kept as a version. Published posts cannot be edited.\n\nRequired scope: `social.write`. Risk level: `write`.","tags":["social"],"security":[{"bearerAuth":["social.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Post id.","schema":{"type":"string","maxLength":60}},{"name":"copy","in":"query","required":false,"description":"New text.","schema":{"type":"string","maxLength":2200}},{"name":"title","in":"query","required":false,"description":"New internal title.","schema":{"type":"string","maxLength":200}},{"name":"headline","in":"query","required":false,"description":"New headline.","schema":{"type":"string","maxLength":200}},{"name":"cta","in":"query","required":false,"description":"New call to action.","schema":{"type":"string","maxLength":60}},{"name":"hashtags","in":"query","required":false,"description":"FULL replacement hashtag list.","schema":{"type":"array","maxItems":8,"items":{"type":"string"}}},{"name":"channels","in":"query","required":false,"description":"FULL replacement channel list.","schema":{"type":"array","maxItems":5,"items":{"type":"string"}}},{"name":"lang","in":"query","required":false,"description":"Language code.","schema":{"type":"string","maxLength":5}},{"name":"format","in":"query","required":false,"description":"image / video / carousel / text.","schema":{"type":"string","maxLength":20}},{"name":"ptype","in":"query","required":false,"description":"Post type.","schema":{"type":"string","enum":["post","story","reel"]}},{"name":"label","in":"query","required":false,"description":"Content label.","schema":{"type":"string","enum":["promo","edu","engage","bts","seasonal","other"]}},{"name":"image","in":"query","required":false,"description":"Hosted image URL.","schema":{"type":"string","maxLength":500}},{"name":"video","in":"query","required":false,"description":"Hosted video URL.","schema":{"type":"string","maxLength":500}},{"name":"link","in":"query","required":false,"description":"Link.","schema":{"type":"string","maxLength":500}},{"name":"scheduledAt","in":"query","required":false,"description":"Intended time (ISO 8601), stored only.","schema":{"type":"string","maxLength":40}},{"name":"status","in":"query","required":false,"description":"draft or pending.","schema":{"type":"string","enum":["draft","pending"]}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"updated":{"type":"boolean","description":"Always true on success."},"post":{"type":"object","properties":{"id":{"type":"string","description":"Post id."},"status":{"type":"string","description":"draft | pending | scheduled | published | rejected."},"title":{"type":"string","description":"Internal title."},"headline":{"type":"string","description":"Headline."},"copy":{"type":"string","description":"Post text (max 2200 chars)."},"cta":{"type":"string","description":"Call to action."},"hashtags":{"type":"array","items":{"type":"string","description":"Hashtag."},"description":"Hashtags."},"channels":{"type":"array","items":{"type":"string","description":"facebook | instagram | linkedin | groups | tiktok."},"description":"Target channels."},"lang":{"type":"string","description":"Language code, e.g. en, he."},"format":{"type":"string","description":"image | video | carousel | text."},"ptype":{"type":"string","description":"post | story | reel."},"label":{"type":"string","description":"Variant label (safe/creative/rtm) or \"\"."},"image":{"type":"string","description":"Image URL or \"\"."},"video":{"type":"string","description":"Video URL or \"\"."},"link":{"type":"string","description":"Link URL or \"\"."},"pageName":{"type":"string","description":"Connected page name or \"\"."},"scheduledAt":{"type":"string","description":"ISO 8601 or \"\"."},"publishedAt":{"type":"string","description":"ISO 8601 or \"\"."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."},"updatedAt":{"type":"string","description":"ISO 8601 or \"\"."},"clientApproved":{"type":"boolean","description":"Client approval flag."},"stats":{"type":"object","properties":{"reach":{"type":"number","description":"Reach."},"impressions":{"type":"number","description":"Impressions."},"engagement":{"type":"number","description":"Engagement count."},"clicks":{"type":"number","description":"Clicks."},"likes":{"type":"number","description":"Likes."},"comments":{"type":"number","description":"Comments."}},"additionalProperties":true,"description":"Live network stats when available."},"leads":{"type":"number","description":"Leads attributed to the post."}},"additionalProperties":true,"required":["id","status","title","headline","copy","cta","hashtags","channels","lang","format","ptype","label","image","video","link","pageName","scheduledAt","publishedAt","createdAt","updatedAt","clientApproved","leads"],"description":"A social calendar post."},"targetType":{"type":"string","enum":["social_post"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Post id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","updated","post","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/social/posts/{id}/status":{"post":{"operationId":"set_social_post_status","summary":"Move a post between draft, pending (client approval) and rejected","description":"Move a post between draft, pending (client approval) and rejected. Setting draft also un-schedules it. Use schedule_social_post / publish_social_post to go live.\n\nRequired scope: `social.write`. Risk level: `write`.","tags":["social"],"security":[{"bearerAuth":["social.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Post id.","schema":{"type":"string","maxLength":60}},{"name":"status","in":"query","required":true,"description":"Target status.","schema":{"type":"string","enum":["draft","pending","rejected"]}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"post":{"type":"object","properties":{"id":{"type":"string","description":"Post id."},"status":{"type":"string","description":"draft | pending | scheduled | published | rejected."},"title":{"type":"string","description":"Internal title."},"headline":{"type":"string","description":"Headline."},"copy":{"type":"string","description":"Post text (max 2200 chars)."},"cta":{"type":"string","description":"Call to action."},"hashtags":{"type":"array","items":{"type":"string","description":"Hashtag."},"description":"Hashtags."},"channels":{"type":"array","items":{"type":"string","description":"facebook | instagram | linkedin | groups | tiktok."},"description":"Target channels."},"lang":{"type":"string","description":"Language code, e.g. en, he."},"format":{"type":"string","description":"image | video | carousel | text."},"ptype":{"type":"string","description":"post | story | reel."},"label":{"type":"string","description":"Variant label (safe/creative/rtm) or \"\"."},"image":{"type":"string","description":"Image URL or \"\"."},"video":{"type":"string","description":"Video URL or \"\"."},"link":{"type":"string","description":"Link URL or \"\"."},"pageName":{"type":"string","description":"Connected page name or \"\"."},"scheduledAt":{"type":"string","description":"ISO 8601 or \"\"."},"publishedAt":{"type":"string","description":"ISO 8601 or \"\"."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."},"updatedAt":{"type":"string","description":"ISO 8601 or \"\"."},"clientApproved":{"type":"boolean","description":"Client approval flag."},"stats":{"type":"object","properties":{"reach":{"type":"number","description":"Reach."},"impressions":{"type":"number","description":"Impressions."},"engagement":{"type":"number","description":"Engagement count."},"clicks":{"type":"number","description":"Clicks."},"likes":{"type":"number","description":"Likes."},"comments":{"type":"number","description":"Comments."}},"additionalProperties":true,"description":"Live network stats when available."},"leads":{"type":"number","description":"Leads attributed to the post."}},"additionalProperties":true,"required":["id","status","title","headline","copy","cta","hashtags","channels","lang","format","ptype","label","image","video","link","pageName","scheduledAt","publishedAt","createdAt","updatedAt","clientApproved","leads"],"description":"A social calendar post."},"targetType":{"type":"string","enum":["social_post"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Post id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","post","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/social/posts/{id}/schedule":{"post":{"operationId":"schedule_social_post","summary":"Arm a post to publish automatically at scheduledAt on its channels","description":"Arm a post to publish automatically at scheduledAt on its channels. PREVIEW FIRST: without confirm it shows the post, channels and time. If the workspace requires client approval, the post goes to pending instead.\n\nRequired scope: `social.publish`. Risk level: `high`.","tags":["social"],"security":[{"bearerAuth":["social.publish"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Post id.","schema":{"type":"string","maxLength":60}},{"name":"scheduledAt","in":"query","required":true,"description":"ISO 8601 date-time in the future.","schema":{"type":"string","maxLength":40}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"willSchedule":{"type":"object","properties":{"id":{"type":"string","description":"Post id."},"status":{"type":"string","description":"draft | pending | scheduled | published | rejected."},"title":{"type":"string","description":"Internal title."},"headline":{"type":"string","description":"Headline."},"copy":{"type":"string","description":"Post text (max 2200 chars)."},"cta":{"type":"string","description":"Call to action."},"hashtags":{"type":"array","items":{"type":"string","description":"Hashtag."},"description":"Hashtags."},"channels":{"type":"array","items":{"type":"string","description":"facebook | instagram | linkedin | groups | tiktok."},"description":"Target channels."},"lang":{"type":"string","description":"Language code, e.g. en, he."},"format":{"type":"string","description":"image | video | carousel | text."},"ptype":{"type":"string","description":"post | story | reel."},"label":{"type":"string","description":"Variant label (safe/creative/rtm) or \"\"."},"image":{"type":"string","description":"Image URL or \"\"."},"video":{"type":"string","description":"Video URL or \"\"."},"link":{"type":"string","description":"Link URL or \"\"."},"pageName":{"type":"string","description":"Connected page name or \"\"."},"scheduledAt":{"type":"string","description":"ISO 8601 or \"\"."},"publishedAt":{"type":"string","description":"ISO 8601 or \"\"."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."},"updatedAt":{"type":"string","description":"ISO 8601 or \"\"."},"clientApproved":{"type":"boolean","description":"Client approval flag."},"stats":{"type":"object","properties":{"reach":{"type":"number","description":"Reach."},"impressions":{"type":"number","description":"Impressions."},"engagement":{"type":"number","description":"Engagement count."},"clicks":{"type":"number","description":"Clicks."},"likes":{"type":"number","description":"Likes."},"comments":{"type":"number","description":"Comments."}},"additionalProperties":true,"description":"Live network stats when available."},"leads":{"type":"number","description":"Leads attributed to the post."}},"additionalProperties":true,"required":["id","status","title","headline","copy","cta","hashtags","channels","lang","format","ptype","label","image","video","link","pageName","scheduledAt","publishedAt","createdAt","updatedAt","clientApproved","leads"],"description":"Preview only: the post that would be scheduled."},"at":{"type":"string","description":"Preview only: scheduled time, ISO 8601."},"channels":{"type":"array","items":{"type":"string","description":"Channel."},"description":"Preview only: channels it will go to."},"warning":{"type":"string","description":"Preview only: consequences of confirming."},"scheduled":{"type":"boolean","description":"Run only: true when scheduled (false when approval-gated)."},"pendingApproval":{"type":"boolean","description":"Run only: true when it now waits for client approval instead."},"post":{"type":"object","properties":{"id":{"type":"string","description":"Post id."},"status":{"type":"string","description":"draft | pending | scheduled | published | rejected."},"title":{"type":"string","description":"Internal title."},"headline":{"type":"string","description":"Headline."},"copy":{"type":"string","description":"Post text (max 2200 chars)."},"cta":{"type":"string","description":"Call to action."},"hashtags":{"type":"array","items":{"type":"string","description":"Hashtag."},"description":"Hashtags."},"channels":{"type":"array","items":{"type":"string","description":"facebook | instagram | linkedin | groups | tiktok."},"description":"Target channels."},"lang":{"type":"string","description":"Language code, e.g. en, he."},"format":{"type":"string","description":"image | video | carousel | text."},"ptype":{"type":"string","description":"post | story | reel."},"label":{"type":"string","description":"Variant label (safe/creative/rtm) or \"\"."},"image":{"type":"string","description":"Image URL or \"\"."},"video":{"type":"string","description":"Video URL or \"\"."},"link":{"type":"string","description":"Link URL or \"\"."},"pageName":{"type":"string","description":"Connected page name or \"\"."},"scheduledAt":{"type":"string","description":"ISO 8601 or \"\"."},"publishedAt":{"type":"string","description":"ISO 8601 or \"\"."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."},"updatedAt":{"type":"string","description":"ISO 8601 or \"\"."},"clientApproved":{"type":"boolean","description":"Client approval flag."},"stats":{"type":"object","properties":{"reach":{"type":"number","description":"Reach."},"impressions":{"type":"number","description":"Impressions."},"engagement":{"type":"number","description":"Engagement count."},"clicks":{"type":"number","description":"Clicks."},"likes":{"type":"number","description":"Likes."},"comments":{"type":"number","description":"Comments."}},"additionalProperties":true,"description":"Live network stats when available."},"leads":{"type":"number","description":"Leads attributed to the post."}},"additionalProperties":true,"required":["id","status","title","headline","copy","cta","hashtags","channels","lang","format","ptype","label","image","video","link","pageName","scheduledAt","publishedAt","createdAt","updatedAt","clientApproved","leads"],"description":"Run only: the post after the status change."},"targetType":{"type":"string","enum":["social_post"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Post id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/social/posts/{id}/publish":{"post":{"operationId":"publish_social_post","summary":"Publish a post NOW to the connected Facebook Page / Instagram / LinkedIn / Groups / TikTok","description":"Publish a post NOW to the connected Facebook Page / Instagram / LinkedIn / Groups / TikTok. PREVIEW FIRST: without confirm it shows exactly what goes where. Cannot be recalled by this tool.\n\nRequired scope: `social.publish`. Risk level: `high`.","tags":["social"],"security":[{"bearerAuth":["social.publish"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Post id.","schema":{"type":"string","maxLength":60}},{"name":"channels","in":"query","required":false,"description":"Override the post's channels.","schema":{"type":"array","maxItems":5,"items":{"type":"string"}}},{"name":"pageId","in":"query","required":false,"description":"Facebook Page id to publish from (default: the focused/first page).","schema":{"type":"string","maxLength":40}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"willPublish":{"type":"object","properties":{"id":{"type":"string","description":"Post id."},"status":{"type":"string","description":"draft | pending | scheduled | published | rejected."},"title":{"type":"string","description":"Internal title."},"headline":{"type":"string","description":"Headline."},"copy":{"type":"string","description":"Post text (max 2200 chars)."},"cta":{"type":"string","description":"Call to action."},"hashtags":{"type":"array","items":{"type":"string","description":"Hashtag."},"description":"Hashtags."},"channels":{"type":"array","items":{"type":"string","description":"facebook | instagram | linkedin | groups | tiktok."},"description":"Target channels."},"lang":{"type":"string","description":"Language code, e.g. en, he."},"format":{"type":"string","description":"image | video | carousel | text."},"ptype":{"type":"string","description":"post | story | reel."},"label":{"type":"string","description":"Variant label (safe/creative/rtm) or \"\"."},"image":{"type":"string","description":"Image URL or \"\"."},"video":{"type":"string","description":"Video URL or \"\"."},"link":{"type":"string","description":"Link URL or \"\"."},"pageName":{"type":"string","description":"Connected page name or \"\"."},"scheduledAt":{"type":"string","description":"ISO 8601 or \"\"."},"publishedAt":{"type":"string","description":"ISO 8601 or \"\"."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."},"updatedAt":{"type":"string","description":"ISO 8601 or \"\"."},"clientApproved":{"type":"boolean","description":"Client approval flag."},"stats":{"type":"object","properties":{"reach":{"type":"number","description":"Reach."},"impressions":{"type":"number","description":"Impressions."},"engagement":{"type":"number","description":"Engagement count."},"clicks":{"type":"number","description":"Clicks."},"likes":{"type":"number","description":"Likes."},"comments":{"type":"number","description":"Comments."}},"additionalProperties":true,"description":"Live network stats when available."},"leads":{"type":"number","description":"Leads attributed to the post."}},"additionalProperties":true,"required":["id","status","title","headline","copy","cta","hashtags","channels","lang","format","ptype","label","image","video","link","pageName","scheduledAt","publishedAt","createdAt","updatedAt","clientApproved","leads"],"description":"Preview only: the post that would be published."},"channels":{"type":"array","items":{"type":"string","description":"Channel."},"description":"Preview only: channels it will publish to."},"warning":{"type":"string","description":"Preview only: consequences of confirming."},"published":{"type":"boolean","description":"Run only: true when at least one channel succeeded."},"results":{"type":"array","items":{"type":"object","properties":{"channel":{"type":"string","description":"facebook | instagram | linkedin | groups | tiktok."},"ok":{"type":"boolean","description":"true when that channel published."},"id":{"type":"string","description":"Network post id."},"url":{"type":"string","description":"Public URL of the live post."},"error":{"type":"string","description":"Failure reason when ok=false."},"note":{"type":"string","description":"Extra note from the network."},"group":{"type":"string","description":"Facebook group name (groups channel)."},"kind":{"type":"string","description":"e.g. \"reel\"."},"demo":{"type":"boolean","description":"true when the LinkedIn post was simulated."},"pending":{"type":"boolean","description":"TikTok: true while the network is still processing."}},"additionalProperties":true,"required":["channel","ok"]},"description":"Run only: one result per channel attempted."},"targetType":{"type":"string","enum":["social_post"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Post id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/social/posts/{id}/delete":{"post":{"operationId":"delete_social_post","summary":"Remove a post from the calendar","description":"Remove a post from the calendar. PREVIEW FIRST. For a published post only the calendar record is removed — the live post stays on the network.\n\nRequired scope: `records.delete`. Risk level: `high`.","tags":["records"],"security":[{"bearerAuth":["records.delete"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Post id.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"willDelete":{"type":"object","properties":{"id":{"type":"string","description":"Post id."},"status":{"type":"string","description":"draft | pending | scheduled | published | rejected."},"title":{"type":"string","description":"Internal title."},"headline":{"type":"string","description":"Headline."},"copy":{"type":"string","description":"Post text (max 2200 chars)."},"cta":{"type":"string","description":"Call to action."},"hashtags":{"type":"array","items":{"type":"string","description":"Hashtag."},"description":"Hashtags."},"channels":{"type":"array","items":{"type":"string","description":"facebook | instagram | linkedin | groups | tiktok."},"description":"Target channels."},"lang":{"type":"string","description":"Language code, e.g. en, he."},"format":{"type":"string","description":"image | video | carousel | text."},"ptype":{"type":"string","description":"post | story | reel."},"label":{"type":"string","description":"Variant label (safe/creative/rtm) or \"\"."},"image":{"type":"string","description":"Image URL or \"\"."},"video":{"type":"string","description":"Video URL or \"\"."},"link":{"type":"string","description":"Link URL or \"\"."},"pageName":{"type":"string","description":"Connected page name or \"\"."},"scheduledAt":{"type":"string","description":"ISO 8601 or \"\"."},"publishedAt":{"type":"string","description":"ISO 8601 or \"\"."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."},"updatedAt":{"type":"string","description":"ISO 8601 or \"\"."},"clientApproved":{"type":"boolean","description":"Client approval flag."},"stats":{"type":"object","properties":{"reach":{"type":"number","description":"Reach."},"impressions":{"type":"number","description":"Impressions."},"engagement":{"type":"number","description":"Engagement count."},"clicks":{"type":"number","description":"Clicks."},"likes":{"type":"number","description":"Likes."},"comments":{"type":"number","description":"Comments."}},"additionalProperties":true,"description":"Live network stats when available."},"leads":{"type":"number","description":"Leads attributed to the post."}},"additionalProperties":true,"required":["id","status","title","headline","copy","cta","hashtags","channels","lang","format","ptype","label","image","video","link","pageName","scheduledAt","publishedAt","createdAt","updatedAt","clientApproved","leads"],"description":"Preview only: the post that would be removed."},"warning":{"type":"string","description":"Preview only: consequences of confirming."},"deleted":{"type":"boolean","description":"Run only: true on success."},"id":{"type":"string","description":"Run only: deleted post id."},"targetType":{"type":"string","enum":["social_post"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Post id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/coupons":{"get":{"operationId":"list_coupons","summary":"Coupons defined for the connected stores with their stats: codes issued, redeemed, attributed revenue, unused pool size (unique-code coupons), status and expiry","description":"Coupons defined for the connected stores with their stats: codes issued, redeemed, attributed revenue, unused pool size (unique-code coupons), status and expiry.\n\nRequired scope: `coupons.read`. Risk level: `read`.","tags":["coupons"],"security":[{"bearerAuth":["coupons.read"]}],"parameters":[{"name":"siteId","in":"query","required":false,"description":"Only coupons of this store (from list_stores).","schema":{"type":"string","maxLength":80}},{"name":"status","in":"query","required":false,"description":"active or paused.","schema":{"type":"string","enum":["active","paused"]}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"coupons":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Coupon id (cpn_…)."},"name":{"type":"string","description":"Coupon token name."},"siteId":{"type":"string","description":"Store (site) id."},"mode":{"type":"string","enum":["shared","unique"],"description":"shared = one code; unique = per-contact codes."},"type":{"type":"string","enum":["percent","fixed"],"description":"Discount type."},"value":{"type":"number","description":"Discount value (% or store currency)."},"minOrder":{"type":"number","description":"Minimum order amount, 0 = none."},"expiry":{"type":"object","properties":{"kind":{"type":"string","enum":["none","date","days"],"description":"Expiry kind."},"date":{"type":"string","description":"YYYY-MM-DD when kind=date."},"days":{"type":"integer","description":"Days valid after issue when kind=days."}},"additionalProperties":true,"required":["kind"],"description":"Expiry rule."},"code":{"type":"string","description":"The shared code (shared mode only)."},"prefix":{"type":"string","description":"Code prefix."},"usageLimit":{"type":"integer","description":"Max uses per code, 0 = unlimited."},"status":{"type":"string","enum":["active","paused"],"description":"Coupon status."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."},"stats":{"type":"object","properties":{"issued":{"type":"integer","description":"Codes issued."},"redeemed":{"type":"integer","description":"Codes redeemed."},"revenue":{"type":"number","description":"Revenue attributed, store currency, 2 decimals."}},"additionalProperties":true,"required":["issued","redeemed","revenue"],"description":"Usage totals."},"unusedCodesInPool":{"type":"integer","description":"Unused pre-generated codes (unique mode)."}},"additionalProperties":true,"required":["id","name","siteId","mode","type","value","minOrder","expiry","prefix","usageLimit","status","createdAt","stats"],"description":"A coupon definition."},"description":"Coupon definitions (filtered by siteId/status)."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"Current page, 1-based."},"pageSize":{"type":"integer","description":"Rows per page after clamping."},"total":{"type":"integer","description":"Total rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"true when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the list (lib/mcp/schema.js paginate)."}},"additionalProperties":true,"required":["ok","requestId","coupons","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"create_coupon","summary":"Create a coupon on a connected store (WooCommerce/Shopify): shared (one code for everyone) or unique (a pool of one-per-contact codes, usable as {{coupon","description":"Create a coupon on a connected store (WooCommerce/Shopify): shared (one code for everyone) or unique (a pool of one-per-contact codes, usable as {{coupon.NAME}} in emails/SMS). Registers the code(s) in the store. The store must already be connected for coupons in the app.\n\nRequired scope: `coupons.write`. Risk level: `write`.","tags":["coupons"],"security":[{"bearerAuth":["coupons.write"]}],"parameters":[{"name":"name","in":"query","required":true,"description":"Token name (letters/numbers/underscore), e.g. SPRING20.","schema":{"type":"string","maxLength":40}},{"name":"siteId","in":"query","required":true,"description":"Store id from list_stores.","schema":{"type":"string","maxLength":80}},{"name":"mode","in":"query","required":false,"description":"shared (default) or unique.","schema":{"type":"string","enum":["shared","unique"]}},{"name":"type","in":"query","required":false,"description":"percent (default) or fixed amount.","schema":{"type":"string","enum":["percent","fixed"]}},{"name":"value","in":"query","required":true,"description":"Discount value.","schema":{"type":"number","minimum":0.01,"maximum":100000}},{"name":"minOrder","in":"query","required":false,"description":"Minimum order total.","schema":{"type":"number","minimum":0,"maximum":1000000}},{"name":"expiresOn","in":"query","required":false,"description":"Fixed expiry date YYYY-MM-DD.","schema":{"type":"string","maxLength":10}},{"name":"validDays","in":"query","required":false,"description":"Alternatively: valid this many days after issue.","schema":{"type":"integer","minimum":1,"maximum":365}},{"name":"code","in":"query","required":false,"description":"Shared mode: the exact code (default = name).","schema":{"type":"string","maxLength":30}},{"name":"prefix","in":"query","required":false,"description":"Unique mode: code prefix.","schema":{"type":"string","maxLength":12}},{"name":"usageLimit","in":"query","required":false,"description":"Max uses per code (0 = unlimited).","schema":{"type":"integer","minimum":0,"maximum":100000}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"created":{"type":"boolean","description":"Always true on success."},"coupon":{"type":"object","properties":{"id":{"type":"string","description":"Coupon id (cpn_…)."},"name":{"type":"string","description":"Coupon token name."},"siteId":{"type":"string","description":"Store (site) id."},"mode":{"type":"string","enum":["shared","unique"],"description":"shared = one code; unique = per-contact codes."},"type":{"type":"string","enum":["percent","fixed"],"description":"Discount type."},"value":{"type":"number","description":"Discount value (% or store currency)."},"minOrder":{"type":"number","description":"Minimum order amount, 0 = none."},"expiry":{"type":"object","properties":{"kind":{"type":"string","enum":["none","date","days"],"description":"Expiry kind."},"date":{"type":"string","description":"YYYY-MM-DD when kind=date."},"days":{"type":"integer","description":"Days valid after issue when kind=days."}},"additionalProperties":true,"required":["kind"],"description":"Expiry rule."},"code":{"type":"string","description":"The shared code (shared mode only)."},"prefix":{"type":"string","description":"Code prefix."},"usageLimit":{"type":"integer","description":"Max uses per code, 0 = unlimited."},"status":{"type":"string","enum":["active","paused"],"description":"Coupon status."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."},"stats":{"type":"object","properties":{"issued":{"type":"integer","description":"Codes issued."},"redeemed":{"type":"integer","description":"Codes redeemed."},"revenue":{"type":"number","description":"Revenue attributed, store currency, 2 decimals."}},"additionalProperties":true,"required":["issued","redeemed","revenue"],"description":"Usage totals."},"unusedCodesInPool":{"type":"integer","description":"Unused pre-generated codes (unique mode)."}},"additionalProperties":true,"required":["id","name","siteId","mode","type","value","minOrder","expiry","prefix","usageLimit","status","createdAt","stats"],"description":"The new coupon; unusedCodesInPool = codes pre-generated (unique mode)."},"targetType":{"type":"string","enum":["coupon"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"New coupon id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","created","coupon","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/coupons/{id}/status":{"post":{"operationId":"set_coupon_status","summary":"Pause a coupon (stops issuing new codes; existing codes keep working in the store) or re-activate it","description":"Pause a coupon (stops issuing new codes; existing codes keep working in the store) or re-activate it.\n\nRequired scope: `coupons.write`. Risk level: `write`.","tags":["coupons"],"security":[{"bearerAuth":["coupons.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Coupon id.","schema":{"type":"string","maxLength":60}},{"name":"status","in":"query","required":true,"description":"active or paused.","schema":{"type":"string","enum":["active","paused"]}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"id":{"type":"string","description":"Coupon id."},"status":{"type":"string","enum":["active","paused"],"description":"New status."},"targetType":{"type":"string","enum":["coupon"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Coupon id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","id","status","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/coupons/{id}/issue":{"post":{"operationId":"issue_coupon_code","summary":"Get the code for one contact: shared coupons return the shared code; unique coupons reserve a code for that email (idempotent — the same contact always gets the same code)","description":"Get the code for one contact: shared coupons return the shared code; unique coupons reserve a code for that email (idempotent — the same contact always gets the same code).\n\nRequired scope: `coupons.write`. Risk level: `write`.","tags":["coupons"],"security":[{"bearerAuth":["coupons.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Coupon id.","schema":{"type":"string","maxLength":60}},{"name":"email","in":"query","required":true,"description":"Contact email the code is for.","schema":{"type":"string","maxLength":160}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"code":{"type":"string","description":"The coupon code for that contact."},"note":{"type":"string","description":"Whether the code is shared or reserved for the contact."},"targetType":{"type":"string","enum":["coupon"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Coupon id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","code","note","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/coupons/{id}/delete":{"post":{"operationId":"delete_coupon","summary":"Delete a coupon definition and its unused code pool","description":"Delete a coupon definition and its unused code pool. PREVIEW FIRST. Codes already registered in the store are left untouched (so codes already in inboxes keep working).\n\nRequired scope: `records.delete`. Risk level: `high`.","tags":["records"],"security":[{"bearerAuth":["records.delete"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Coupon id.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"willDelete":{"type":"object","properties":{"id":{"type":"string","description":"Coupon id (cpn_…)."},"name":{"type":"string","description":"Coupon token name."},"siteId":{"type":"string","description":"Store (site) id."},"mode":{"type":"string","enum":["shared","unique"],"description":"shared = one code; unique = per-contact codes."},"type":{"type":"string","enum":["percent","fixed"],"description":"Discount type."},"value":{"type":"number","description":"Discount value (% or store currency)."},"minOrder":{"type":"number","description":"Minimum order amount, 0 = none."},"expiry":{"type":"object","properties":{"kind":{"type":"string","enum":["none","date","days"],"description":"Expiry kind."},"date":{"type":"string","description":"YYYY-MM-DD when kind=date."},"days":{"type":"integer","description":"Days valid after issue when kind=days."}},"additionalProperties":true,"required":["kind"],"description":"Expiry rule."},"code":{"type":"string","description":"The shared code (shared mode only)."},"prefix":{"type":"string","description":"Code prefix."},"usageLimit":{"type":"integer","description":"Max uses per code, 0 = unlimited."},"status":{"type":"string","enum":["active","paused"],"description":"Coupon status."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."},"stats":{"type":"object","properties":{"issued":{"type":"integer","description":"Codes issued."},"redeemed":{"type":"integer","description":"Codes redeemed."},"revenue":{"type":"number","description":"Revenue attributed, store currency, 2 decimals."}},"additionalProperties":true,"required":["issued","redeemed","revenue"],"description":"Usage totals."},"unusedCodesInPool":{"type":"integer","description":"Unused pre-generated codes (unique mode)."}},"additionalProperties":true,"required":["id","name","siteId","mode","type","value","minOrder","expiry","prefix","usageLimit","status","createdAt","stats"],"description":"Preview only: the coupon that would be deleted."},"warning":{"type":"string","description":"Preview only: consequences of confirming."},"deleted":{"type":"boolean","description":"Run only: true on success."},"id":{"type":"string","description":"Run only: deleted coupon id."},"note":{"type":"string","description":"Run only: what happened to codes already in the store."},"targetType":{"type":"string","enum":["coupon"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Coupon id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/meetings/pages":{"get":{"operationId":"list_booking_pages","summary":"The user's public booking pages (/book/{slug}): title, duration, buffer, availability windows per weekday (0=Sunday), horizon and public URL","description":"The user's public booking pages (/book/{slug}): title, duration, buffer, availability windows per weekday (0=Sunday), horizon and public URL.\n\nRequired scope: `meetings.read`. Risk level: `read`.","tags":["meetings"],"security":[{"bearerAuth":["meetings.read"]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"pages":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string","description":"Page slug."},"url":{"type":"string","description":"Public URL https://app.fortvision.com/book/{slug}."},"title":{"type":"string","description":"Page title."},"description":{"type":"string","description":"Description or \"\"."},"durationMin":{"type":"number","description":"Meeting length in minutes."},"bufferMin":{"type":"number","description":"Buffer between meetings, minutes."},"daysAhead":{"type":"number","description":"How many days ahead can be booked."},"timezone":{"type":"string","description":"IANA timezone, default Asia/Jerusalem."},"availability":{"type":"object","additionalProperties":true,"description":"Weekday (0=Sun…6=Sat) → array of [start \"HH:MM\", end \"HH:MM\"] windows."},"active":{"type":"boolean","description":"false when the page is switched off."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."}},"additionalProperties":true,"required":["slug","url","title","description","bufferMin","timezone","availability","active","createdAt"],"description":"A public booking page."},"description":"Booking pages of this workspace."}},"additionalProperties":true,"required":["ok","requestId","pages"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"save_booking_page","summary":"Create or update a booking page (pass an existing slug to update)","description":"Create or update a booking page (pass an existing slug to update). availability maps weekday (0=Sunday…6=Saturday) to up to 3 [from, to] windows in HH:MM, Israel time; default Sun-Thu 09:00-17:00. Returns the public /book/ URL.\n\nRequired scope: `meetings.write`. Risk level: `write`.","tags":["meetings"],"security":[{"bearerAuth":["meetings.write"]}],"parameters":[{"name":"title","in":"query","required":true,"description":"Page title, e.g. \"Intro call\".","schema":{"type":"string","maxLength":120}},{"name":"slug","in":"query","required":false,"description":"URL slug (a-z, 0-9, dashes). Default: derived from the title.","schema":{"type":"string","maxLength":60}},{"name":"description","in":"query","required":false,"description":"Shown to invitees.","schema":{"type":"string","maxLength":300}},{"name":"durationMin","in":"query","required":false,"description":"Meeting length in minutes (10-240, default 30).","schema":{"type":"integer","minimum":10,"maximum":240}},{"name":"bufferMin","in":"query","required":false,"description":"Gap after each meeting (0-120).","schema":{"type":"integer","minimum":0,"maximum":120}},{"name":"daysAhead","in":"query","required":false,"description":"How far ahead invitees may book (1-60, default 30).","schema":{"type":"integer","minimum":1,"maximum":60}},{"name":"availability","in":"query","required":false,"description":"e.g. {\"0\":[[\"09:00\",\"13:00\"]],\"1\":[[\"09:00\",\"17:00\"]]}","schema":{"type":"string"}},{"name":"active","in":"query","required":false,"description":"false hides the page without deleting it.","schema":{"type":"boolean"}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"saved":{"type":"boolean","description":"Always true on success."},"page":{"type":"object","properties":{"slug":{"type":"string","description":"Page slug."},"url":{"type":"string","description":"Public URL https://app.fortvision.com/book/{slug}."},"title":{"type":"string","description":"Page title."},"description":{"type":"string","description":"Description or \"\"."},"durationMin":{"type":"number","description":"Meeting length in minutes."},"bufferMin":{"type":"number","description":"Buffer between meetings, minutes."},"daysAhead":{"type":"number","description":"How many days ahead can be booked."},"timezone":{"type":"string","description":"IANA timezone, default Asia/Jerusalem."},"availability":{"type":"object","additionalProperties":true,"description":"Weekday (0=Sun…6=Sat) → array of [start \"HH:MM\", end \"HH:MM\"] windows."},"active":{"type":"boolean","description":"false when the page is switched off."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."}},"additionalProperties":true,"required":["slug","url","title","description","bufferMin","timezone","availability","active","createdAt"],"description":"A public booking page."},"url":{"type":"string","description":"Public booking URL."},"targetType":{"type":"string","enum":["booking_page"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Page slug."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","saved","page","url","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/meetings/bookings":{"get":{"operationId":"list_bookings","summary":"Meetings booked through the booking pages: who, when, for which page, status (confirmed / cancelled)","description":"Meetings booked through the booking pages: who, when, for which page, status (confirmed / cancelled). Soonest first; upcomingOnly hides past meetings.\n\nRequired scope: `meetings.read`. Risk level: `read`.","tags":["meetings"],"security":[{"bearerAuth":["meetings.read"]}],"parameters":[{"name":"status","in":"query","required":false,"description":"confirmed or cancelled.","schema":{"type":"string","enum":["confirmed","cancelled"]}},{"name":"upcomingOnly","in":"query","required":false,"description":"Only meetings in the future.","schema":{"type":"boolean","default":false}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Results per page (max 100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"bookings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Booking id."},"pageSlug":{"type":"string","description":"Booking page slug."},"pageTitle":{"type":"string","description":"Booking page title or \"\"."},"start":{"type":"string","description":"Meeting start, ISO 8601."},"durationMin":{"type":"number","description":"Duration in minutes."},"name":{"type":"string","description":"Invitee name."},"email":{"type":"string","description":"Invitee email."},"phone":{"type":"string","description":"Invitee phone."},"note":{"type":"string","description":"Invitee note."},"status":{"type":"string","description":"confirmed (default) or cancelled."},"bookedAt":{"type":"string","description":"ISO 8601 when booked, or \"\"."}},"additionalProperties":true,"required":["id","pageSlug","pageTitle","start","durationMin","name","email","phone","note","status","bookedAt"],"description":"A booked meeting."},"description":"Bookings sorted by start time (filtered by status/upcomingOnly)."},"pagination":{"type":"object","properties":{"page":{"type":"integer","description":"Current page, 1-based."},"pageSize":{"type":"integer","description":"Rows per page after clamping."},"total":{"type":"integer","description":"Total rows across all pages."},"totalPages":{"type":"integer","description":"Number of pages (at least 1)."},"hasMore":{"type":"boolean","description":"true when a later page exists."}},"additionalProperties":true,"required":["page","pageSize","total","totalPages","hasMore"],"description":"Page window applied to the list (lib/mcp/schema.js paginate)."}},"additionalProperties":true,"required":["ok","requestId","bookings","pagination"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/meetings/bookings/{id}/cancel":{"post":{"operationId":"cancel_booking","summary":"Cancel a booked meeting and free its slot","description":"Cancel a booked meeting and free its slot. PREVIEW FIRST. The invitee is not notified automatically.\n\nRequired scope: `records.delete`. Risk level: `high`.","tags":["records"],"security":[{"bearerAuth":["records.delete"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Booking id from list_bookings.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"willCancel":{"type":"object","properties":{"id":{"type":"string","description":"Booking id."},"pageSlug":{"type":"string","description":"Booking page slug."},"pageTitle":{"type":"string","description":"Booking page title or \"\"."},"start":{"type":"string","description":"Meeting start, ISO 8601."},"durationMin":{"type":"number","description":"Duration in minutes."},"name":{"type":"string","description":"Invitee name."},"email":{"type":"string","description":"Invitee email."},"phone":{"type":"string","description":"Invitee phone."},"note":{"type":"string","description":"Invitee note."},"status":{"type":"string","description":"confirmed (default) or cancelled."},"bookedAt":{"type":"string","description":"ISO 8601 when booked, or \"\"."}},"additionalProperties":true,"required":["id","pageSlug","pageTitle","start","durationMin","name","email","phone","note","status","bookedAt"],"description":"Preview only: the booking that would be cancelled."},"warning":{"type":"string","description":"Preview only: consequences of confirming."},"cancelled":{"type":"boolean","description":"Run only: true on success."},"id":{"type":"string","description":"Run only: cancelled booking id."},"targetType":{"type":"string","enum":["booking"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Booking id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/meetings/pages/{slug}/delete":{"post":{"operationId":"delete_booking_page","summary":"Delete a booking page (its public link stops working)","description":"Delete a booking page (its public link stops working). PREVIEW FIRST. Existing bookings are kept.\n\nRequired scope: `records.delete`. Risk level: `high`.","tags":["records"],"security":[{"bearerAuth":["records.delete"]}],"parameters":[{"name":"slug","in":"path","required":true,"description":"Page slug.","schema":{"type":"string","maxLength":60}},{"name":"idempotencyKey","in":"query","required":true,"description":"A unique id for THIS action (required). Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}},{"name":"confirm","in":"query","required":false,"description":"Leave false (the default) to PREVIEW: nothing changes and you get a summary plus a confirmationToken. Set true and pass that token to actually perform the action.","schema":{"type":"boolean","default":false}},{"name":"confirmationToken","in":"query","required":false,"description":"The token returned by the preview call. Required when confirm is true. It is tied to the exact arguments you previewed, is single-use, and expires after 15 minutes.","schema":{"type":"string","maxLength":80}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"willDelete":{"type":"object","properties":{"slug":{"type":"string","description":"Page slug."},"url":{"type":"string","description":"Public URL https://app.fortvision.com/book/{slug}."},"title":{"type":"string","description":"Page title."},"description":{"type":"string","description":"Description or \"\"."},"durationMin":{"type":"number","description":"Meeting length in minutes."},"bufferMin":{"type":"number","description":"Buffer between meetings, minutes."},"daysAhead":{"type":"number","description":"How many days ahead can be booked."},"timezone":{"type":"string","description":"IANA timezone, default Asia/Jerusalem."},"availability":{"type":"object","additionalProperties":true,"description":"Weekday (0=Sun…6=Sat) → array of [start \"HH:MM\", end \"HH:MM\"] windows."},"active":{"type":"boolean","description":"false when the page is switched off."},"createdAt":{"type":"string","description":"ISO 8601 or \"\"."}},"additionalProperties":true,"required":["slug","url","title","description","bufferMin","timezone","availability","active","createdAt"],"description":"Preview only: the page that would be deleted."},"warning":{"type":"string","description":"Preview only: consequences of confirming."},"deleted":{"type":"boolean","description":"Run only: true on success."},"slug":{"type":"string","description":"Run only: deleted page slug."},"targetType":{"type":"string","enum":["booking_page"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Page slug."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."},"status":{"type":"string","enum":["preview"],"description":"Present on a preview call: nothing was changed yet."},"message":{"type":"string","description":"Preview instructions: call again with confirm:true and the confirmationToken to perform the action."},"confirmationToken":{"type":"string","description":"Single-use token bound to these exact arguments; expires after 15 minutes."},"expiresAt":{"type":"string","description":"ISO 8601 expiry of the confirmationToken."},"expiresInSeconds":{"type":"integer","description":"Seconds until the confirmationToken expires."}},"additionalProperties":true,"required":["ok","requestId","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/automations/{id}/enabled":{"post":{"operationId":"set_automation_enabled","summary":"Enable or pause an automation (journey)","description":"Enable or pause an automation (journey). Pausing stops the live run too — no new contacts enter and in-flight steps hold — and is fully reversible by enabling again. Does not edit the flow itself; use list_automations / get_automation to pick the id.\n\nRequired scope: `agents.write`. Risk level: `write`.","tags":["agents"],"security":[{"bearerAuth":["agents.write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Automation id.","schema":{"type":"string","maxLength":60}},{"name":"enabled","in":"query","required":true,"description":"true to enable, false to pause.","schema":{"type":"boolean"}},{"name":"idempotencyKey","in":"query","required":false,"description":"A unique id for THIS action. Repeating a call with the same key returns the original result instead of acting twice — use it so a timeout or retry cannot duplicate the write.","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"requestId":{"type":"string"},"id":{"type":"string","description":"Automation id."},"name":{"type":"string","description":"Automation name (\"\" if unnamed)."},"enabled":{"type":"boolean","description":"State after the call."},"wasEnabled":{"type":"boolean","description":"State before the call."},"livePaused":{"type":"boolean","description":"When reported: true if in-flight journey runs were paused too."},"targetType":{"type":"string","enum":["automation"],"description":"Entity type of the affected record."},"targetId":{"type":"string","description":"Automation id."},"idempotentReplay":{"type":"boolean","description":"true when this idempotencyKey was already used: the ORIGINAL result is returned and nothing ran again."}},"additionalProperties":true,"required":["ok","requestId","id","name","enabled","wasEnabled","targetType","targetId"]}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}}}}