Reference
REST API
Every operation the SalesShift control plane serves, generated from an inventory of the running service rather than written by hand. Each entry carries how much is known about it: whether it was called against a live server while these docs were built, or only read in source.
379
operations across 302 paths
28
routers, grouped into the domains below
110
called live while writing these docs
116
request and response models documented
Before you start
Two prefixes cover everything here: /api/v1/salesshift for the 322 SalesShift operations, and /api/v1/messaging for the 57 messaging and call operations. Examples use https://api.vxcloud.io because that is the host every verified call on these pages was made against.
There is no OpenAPI document. app.py constructs FastAPI with docs_url=None, redoc_url=None and openapi_url=None, so /openapi.json and /docs are 404 on the running service. Do not tell readers to browse them.
Authentication
Every endpoint names the dependency that guards it. There are three, and they accept different credentials:
| Dependency | Routes | Accepts | Scope |
|---|---|---|---|
| get_org_user | 296 | Authorization: Bearer <jwt>X-API-Key: xc_<env>_... | Resolves both a user and an organization; every query is filtered by that organization_id. On failure: 401 {"detail": "Not authenticated — provide Bearer token or X-API-Key"} (observed live). |
| get_current_user | 6 | Authorization: Bearer <jwt> | Platform JWT; no organization scoping applied by the dependency. |
| get_current_user_id | 46 | Authorization: Bearer <jwt> | Caller's user id only; room membership is enforced by _require_member inside each handler. On failure: 401 {"detail": "Not authenticated"} (observed live). |
route.auth carries {required, dependency, scope}. The accepted credentials and the exact failure body for each dependency live once, below, under auth_dependencies — look the dependency name up there. The `authorization` and `X-API-Key` headers are deliberately absent from route.params: FastAPI lists them because get_org_user declares them as Header() params, but they are the credential, not an option.
API keys are accepted with the prefixes xc_dev_, xc_live_, xc_test_, xc_stg_, xc_sbx_, xc_prev_. The 46 messaging routes take a Bearer JWT only.
31 endpoints carry no auth dependency — and they are not one list
Do NOT describe these as 'public' as a group. Only the `open` ones take no credential at all; the rest carry the credential somewhere other than an Authorization header, and two of them do a full auth check inside the handler.
- open1No credential of any kind.
- in-handler-auth2A normal credential, resolved by the handler rather than by a Depends(). These are authenticated routes.
- signature-verified2Anonymous caller, but the request body is verified against a stored provider secret.
- url-secret-only17The token, slug or id in the URL is the ONLY credential. Treat those URLs as secrets.
- public-by-design9Meant to be reachable by anyone — published pages, the tracking pixel, and the unsubscribe flow.
Response envelopes
There is no single wrapper. Each endpoint states which of these it uses, so read that line before writing a client against it.
success+data158{success: true, data: ...}, optionally with `pagination`.
success+custom114Has `success`, but the payload is under other keys too — e.g. {success, contact, messages} or {success, data, recipients}.
bare-model12The Pydantic response_model serialised directly. No `success`, no `data` — the model's fields are the top level.
bare-object73A plain object or array with no envelope, built by the handler or a helper.
html9text/html — including the error responses.
binary9A file or image body (PDF, ICS, PNG, attachment, raw message source).
text1text/plain (the CSV report export).
redirect2A 3xx redirect rather than a body.
empty1Returns None — a 200 with a null JSON body.
Errors
Failures are FastAPI's standard shape — an HTTP status and a detail string. Each endpoint lists the ones its own handler raises; where the message is computed, the expression is shown rather than a made-up sample.
{
"detail": "Not authenticated — provide Bearer token or X-API-Key"
}The statuses that carry a distinct meaning across the whole API, rather than one endpoint's own validation:
| Status | What it means here |
|---|---|
| 401 | No credential, or one the server could not verify. Nothing about the request body was looked at. |
| 402 | A plan refusal: the operation would spend something this plan does not include. It is never softened to 403, because the two need different UI — one offers an upgrade, the other does not. The detail string names the plan, the ceiling and the current number and is written to be shown to a user unchanged. |
| 403 | A permission or ownership problem — the credential is valid and the answer is still no. Registering a node that identifies as somebody else's workspace is the clearest example. |
| 404 | No such row, or no such row in your workspace. The two are deliberately indistinguishable. |
| 409 | A duplicate, or a state conflict: the request is well-formed but the workspace is not in a state where it makes sense. POST /billing/activate answers 409 when a live plan would be downgraded. |
| 410 | A pool record erased at the person's request. Terminal and global — not an outage, and retrying will never succeed. |
| 503 | A capability this deployment does not have configured. Every Stripe-touching billing route answers it when no Stripe key is present. |
Where a 402 comes from is answerable in one call: GET /api/v1/salesshift/billing/entitlements returns the resolved plan and every allowance; Plans and self-hosting lists the five places in the product that raise it.
Two paths report a refusal inside a 200 body instead of raising, because both run in loops over many rows and one refused row must not fail the batch. POST /api/v1/salesshift/email/send answers 200 with status: "failed" and provider: "refused", the reason in error; POST /api/v1/salesshift/ai/write-email answers 200 with source: "template" and the reason in reason. A client that reads only the status code will record both as successes.
What the badges mean
live-callCalled against http://127.0.0.1:8741 during this inventory run; the `verified` block holds the request and the response.session-verifiedThe feature was verified working against the live system in the session that produced this inventory, but this specific route was not re-called here.code-onlyRead in source for this inventory and not executed. Undemonstrated is not the same as broken — but do not write it up as proven.known-unprovenOne of the two items in known_unproven.
Do not upgrade a `code-only` route to a worked example in a doc. Either call it first and update this file, or write it as a reference entry without an 'it works like this' claim.
2 capabilities are built but unproven
oauth-mailbox-connect
OAuth mailbox connect is fully built — PKCE, Vault-stored tokens, XOAUTH2 and refresh — and a real send completes AUTH XOAUTH2 -> 250 queued. No Microsoft or Google mailbox has ever consented here, so the final SMTP hop to a real provider is UNPROVEN.
What was actually observed: GET /webmail/oauth/providers returned 200 with configured=true and missing=[] for both microsoft and google, and one account in this org carries auth_method=oauth / oauth_provider=microsoft with oauth_connected_at set. That is client configuration and a local proof account, not consent from a real provider mailbox.
GET /api/v1/salesshift/webmail/oauth/providersPOST /api/v1/salesshift/webmail/oauth/{provider}/connectPOST /api/v1/salesshift/webmail/accounts/{account_id}/reconnectGET /api/v1/salesshift/webmail/oauth/callback
call-transcription-summary
Call transcription and summary have never run with real data. No org has an AI provider key, so every recording ends at status='unavailable'.
What was actually observed: GET /settings/integrations for the test org returned three integrations, all integration_type='email' (imap, smtp, smtp). There is no integration_type='ai' row, which is the condition that leaves transcription unavailable.
POST /api/v1/messaging/calls/{call_id}/recording/chunksPOST /api/v1/messaging/calls/{call_id}/recording/finalizeGET /api/v1/messaging/calls/{call_id}/intelligenceGET /api/v1/messaging/calls/{call_id}/recordings/{recording_id}/filePOST /api/v1/messaging/calls/{call_id}/transcribe
Domains
The full entry for every endpoint — parameters, request and response shapes, error cases, a copyable curl — lives on its domain page.
All 379 endpoints
Filter by path, method or words from the summary. Every row links to its full entry.
379 endpoints
/api/v1/salesshift/companiesPaged, searchable list of company records, each with its contact count.Called livePOST/api/v1/salesshift/companiesCreate a company record owned by the calling user.Not exercised herePUT/api/v1/salesshift/companies/{company_id}Update a company record from a partial payload.Not exercised hereDELETE/api/v1/salesshift/companies/{company_id}Delete a company record.Not exercised hereGET/api/v1/salesshift/contactsPaged, filterable list of the organization's contacts.Called livePOST/api/v1/salesshift/contactsCreate a contact; an existing contact with the same email in the org is returned instead of a duplicate.Not exercised hereGET/api/v1/salesshift/contacts/{contact_id}One contact by id, scoped to the caller's organization.Called livePUT/api/v1/salesshift/contacts/{contact_id}Update a contact from a partial payload (unset fields are left alone).Not exercised hereDELETE/api/v1/salesshift/contacts/{contact_id}Delete a contact and its dependent bookings, deals, email-tracking and form-submission rows.Not exercised hereGET/api/v1/salesshift/contacts/{contact_id}/activitiesThe 100 most recent activity rows recorded against a contact.Called liveGET/api/v1/salesshift/contacts/{contact_id}/enrollmentsSequences this contact is (or was) enrolled in — powers the Sequences tab on the contact profile.Called liveGET/api/v1/salesshift/contacts/{contact_id}/listsThe lists this contact actually belongs to — the profile used to print the organization's list count in that row, which is a different number.Called livePOST/api/v1/salesshift/contacts/{contact_id}/notesAppend a note activity to a contact's timeline.Not exercised herePOST/api/v1/salesshift/contacts/{contact_id}/rescoreRecompute and persist a contact's fit/engagement scores.Not exercised herePOST/api/v1/salesshift/contacts/{contact_id}/send-emailOne-off tracked email to a single contact (the plan's walking skeleton, task 1.9): BYOK/platform send + pixel + unsubscribe link.Not exercised herePOST/api/v1/salesshift/contacts/bulkCSV import (plan 1.7): rows already column-mapped by the frontend wizard.Not exercised herePOST/api/v1/salesshift/contacts/enrichWaterfall enrichment MVP (plan 5.8): Hunter.io via BYOK key when configured, else deterministic email-pattern inference.Not exercised hereGET/api/v1/salesshift/conversationsContacts with email history, newest activity first.Called liveGET/api/v1/salesshift/conversations/{contact_id}Full email thread with one contact: every tracked send + captured reply.Called livePOST/api/v1/salesshift/email/sendDirect tracked send — the vxcli / vxsdk surface.Not exercised hereGET/api/v1/salesshift/listsThe organization's static contact lists with member counts.Called livePOST/api/v1/salesshift/listsCreate a static contact list.Called liveDELETE/api/v1/salesshift/lists/{list_id}Delete a static contact list.Called liveGET/api/v1/salesshift/lists/{list_id}/membersThe contacts belonging to one static list.Called livePOST/api/v1/salesshift/lists/{list_id}/membersAdd contacts to a static list; ids outside the org are ignored.Not exercised hereDELETE/api/v1/salesshift/lists/{list_id}/members/{contact_id}Take one contact out of a list.Not exercised hereGET/api/v1/salesshift/tasksThe organization's CRM tasks, filterable by status, type, priority and free text.Called livePOST/api/v1/salesshift/tasksCreate a CRM task assigned to the calling user.Not exercised herePUT/api/v1/salesshift/tasks/{task_id}Update a CRM task from a partial payload.Not exercised hereDELETE/api/v1/salesshift/tasks/{task_id}Hard-delete a task.Not exercised hereLeads and enrichment
Open reference (17)/api/v1/salesshift/lead-searchesThe organization's saved lead searches.Called livePOST/api/v1/salesshift/lead-searchesSave a named set of pool filters as a reusable search.Not exercised hereGET/api/v1/salesshift/leadsThe organization's saved leads, optionally filtered by status.Called liveGET/api/v1/salesshift/leads/{lead_id}One saved lead, plus the live pool record behind it.Not exercised herePATCH/api/v1/salesshift/leads/{lead_id}Update a saved lead's status, score, notes, disqualify reason, owner or tags.Not exercised herePOST/api/v1/salesshift/leads/{lead_id}/convertLead → Contact.Not exercised herePOST/api/v1/salesshift/leads/bulk-convertConvert many saved leads to contacts in one call, reporting every id's outcome.Not exercised hereGET/api/v1/salesshift/leads/company/{company_id}A company in the pool, with the people behind it split by what this org already owns.Not exercised herePOST/api/v1/salesshift/leads/convert-from-poolPool → Contact in one action: save, reveal if needed, convert.Not exercised herePOST/api/v1/salesshift/leads/enrichCrawl a company's own site and fold what is found back into the pool.Not exercised herePOST/api/v1/salesshift/leads/erasureErase a person from the pool and flag every tenant's saved copy.Not exercised herePOST/api/v1/salesshift/leads/facetsCounts beside each filter.Called liveGET/api/v1/salesshift/leads/pool/{pool_id}Everything the pool knows about one person, plus this org's relationship to them (revealed?Not exercised hereGET/api/v1/salesshift/leads/quotaThe organization's reveal meter: used, allowance and remaining for the period.Called livePOST/api/v1/salesshift/leads/revealUn-mask one pool person's contact details; spends one metered reveal.Called livePOST/api/v1/salesshift/leads/saveCopy pool rows into the tenant's own list.Not exercised herePOST/api/v1/salesshift/leads/searchSearch the global pool.Called liveSequences
Open reference (23)/api/v1/salesshift/sequencesSequence list with real rollups — steps, enrollment breakdown and the send/open/reply funnel measured against ss_email_tracking.Called livePOST/api/v1/salesshift/sequencesCreate an outreach sequence, optionally with its steps.Verified in sessionGET/api/v1/salesshift/sequences/{sequence_id}One sequence with its steps, variants and rollup counters.Called livePUT/api/v1/salesshift/sequences/{sequence_id}Update a sequence and, when supplied, replace its step list.Verified in sessionDELETE/api/v1/salesshift/sequences/{sequence_id}Delete a sequence.Verified in sessionPOST/api/v1/salesshift/sequences/{sequence_id}/activateSet a sequence's status to active so the dispatcher will send its steps.Verified in sessionGET/api/v1/salesshift/sequences/{sequence_id}/analyticsPer-step funnel measured against ss_email_tracking — nothing estimated.Verified in sessionPOST/api/v1/salesshift/sequences/{sequence_id}/archiveSet a sequence's status to archived.Verified in sessionPOST/api/v1/salesshift/sequences/{sequence_id}/duplicateDeep copy: settings + every step + every A/B variant.Verified in sessionPOST/api/v1/salesshift/sequences/{sequence_id}/enrollEnroll contacts by id, by list, or by saved contact filter.Verified in sessionGET/api/v1/salesshift/sequences/{sequence_id}/enrollmentsPaged enrollments for one sequence, joined to the enrolled contact.Verified in sessionDELETE/api/v1/salesshift/sequences/{sequence_id}/enrollments/{enrollment_id}Remove a contact's enrollment and decrement the sequence's enrolled counter.Verified in sessionPOST/api/v1/salesshift/sequences/{sequence_id}/enrollments/{enrollment_id}/pausePause one contact's enrollment in a sequence.Verified in sessionPOST/api/v1/salesshift/sequences/{sequence_id}/enrollments/{enrollment_id}/resumeResume a paused or failed enrollment.Verified in sessionPOST/api/v1/salesshift/sequences/{sequence_id}/pauseSet a sequence's status to paused.Verified in sessionPOST/api/v1/salesshift/sequences/{sequence_id}/previewRender one step's merge fields against a real contact, or against a clearly-flagged sample when no contact is supplied.Verified in sessionPOST/api/v1/salesshift/sequences/{sequence_id}/stepsAppend a step, or insert at `step_number` (1-based) pushing the rest down.Verified in sessionPOST/api/v1/salesshift/sequences/{sequence_id}/steps/reorderRenumber the timeline atomically.Verified in sessionPOST/api/v1/salesshift/sequences/dispatch-nowManually run one dispatch tick for the caller's org (the background loop runs the same engine every minute).Verified in sessionPUT/api/v1/salesshift/steps/{step_id}Update one sequence step, validating step type, condition config and delay.Verified in sessionDELETE/api/v1/salesshift/steps/{step_id}Delete a step (its A/B variants cascade) and close the numbering gap.Verified in sessionPOST/api/v1/salesshift/steps/{step_id}/variantsAdd an A/B variant to an email step.Verified in sessionDELETE/api/v1/salesshift/variants/{variant_id}Delete an A/B variant of a step (use DELETE /steps/{step_id} for a step itself).Verified in sessionCampaigns
Open reference (15)/api/v1/salesshift/campaignsThe organization's campaigns with their tracking rollups.Called livePOST/api/v1/salesshift/campaignsCreate a campaign after validating the sender and resolving the audience.Not exercised hereGET/api/v1/salesshift/campaigns/{campaign_id}One campaign with its stats and per-recipient tracking rows.Called livePATCH/api/v1/salesshift/campaigns/{campaign_id}Edit a campaign; only drafts and scheduled campaigns can be edited.Not exercised hereDELETE/api/v1/salesshift/campaigns/{campaign_id}Delete a campaign.Not exercised herePOST/api/v1/salesshift/campaigns/{campaign_id}/sendSend or schedule a campaign to its resolved audience.Not exercised herePOST/api/v1/salesshift/campaigns/{campaign_id}/test-sendSend one preview copy to a chosen address using a transient probe contact.Not exercised herePOST/api/v1/salesshift/campaigns/{campaign_id}/unschedulePut a scheduled campaign back into draft.Not exercised herePOST/api/v1/salesshift/campaigns/audience-previewResolve lists and contact ids to a sendable audience, reporting what was dropped and the cap.Called liveGET/api/v1/salesshift/campaigns/sendersAvailable sending servers: every active BYOK email integration (multi-SMTP: one entry per configured server, default first) + every active connected mailbox (each one a full SMTP identity).Called liveGET/api/v1/salesshift/campaigns/templatesBuilt-in email templates plus the organization's saved ones.Called livePOST/api/v1/salesshift/campaigns/templatesSave a custom email template.Not exercised herePUT/api/v1/salesshift/campaigns/templates/{template_id}Update a saved email template.Not exercised hereDELETE/api/v1/salesshift/campaigns/templates/{template_id}Delete a saved email template.Not exercised herePOST/api/v1/salesshift/campaigns/templates/seedDrop the starter 1:1 sales library into this org.Not exercised hereDeliverability
Open reference (13)/api/v1/salesshift/deliverability/domain/{domain}SPF / DKIM / DMARC / MX / blocklist for one domain.Verified in sessionGET/api/v1/salesshift/deliverability/domainsEvery sending domain the org's mailboxes use, with the last DNS answer for each.Called liveGET/api/v1/salesshift/deliverability/inboxesThe sending pool: every connected mailbox with its cap, ramp position, health, and — when it is not sending — the reason.Called livePATCH/api/v1/salesshift/deliverability/inboxes/{inbox_id}Change one mailbox's pool policy.Verified in sessionPOST/api/v1/salesshift/deliverability/inboxes/{inbox_id}/pausePause one mailbox in the sending pool with a recorded reason.Verified in sessionPOST/api/v1/salesshift/deliverability/inboxes/{inbox_id}/resumePut a mailbox back in the rotation.Verified in sessionPOST/api/v1/salesshift/deliverability/placement-testSend a probe to the org's seed list and report where it landed.Verified in sessionGET/api/v1/salesshift/deliverability/placement-testsRecent inbox-placement tests and their per-seed results.Called liveGET/api/v1/salesshift/deliverability/seed-listThe organization's seed addresses, joined to any connected webmail account.Called livePOST/api/v1/salesshift/deliverability/seed-listAdd a seed address used by placement tests.Verified in sessionDELETE/api/v1/salesshift/deliverability/seed-list/{seed_id}Remove a seed address.Verified in sessionGET/api/v1/salesshift/deliverability/settingsSending-pool settings: rotation flag, health window and the platform defaults.Called livePATCH/api/v1/salesshift/deliverability/settingsOrg-level pool switches.Verified in sessionWebmail
Open reference (25)/api/v1/salesshift/webmail/accountsMailboxes visible to the caller (shared, unowned, or their own).Called livePOST/api/v1/salesshift/webmail/accountsAdd a custom IMAP/SMTP mailbox; the credentials are proven before the row is saved.Not exercised herePATCH/api/v1/salesshift/webmail/accounts/{account_id}Update a mailbox's settings.Not exercised hereDELETE/api/v1/salesshift/webmail/accounts/{account_id}Remove a mailbox, optionally deleting the underlying provisioned mailbox.Not exercised herePOST/api/v1/salesshift/webmail/accounts/{account_id}/actionBulk message action (read, flag, move, delete, folder operations).Not exercised hereGET/api/v1/salesshift/webmail/accounts/{account_id}/attachmentDownload one attachment from a message by index.Not exercised hereGET/api/v1/salesshift/webmail/accounts/{account_id}/foldersList the IMAP folders on a mailbox.Not exercised hereGET/api/v1/salesshift/webmail/accounts/{account_id}/messageOne full message by UID, optionally marking it seen.Not exercised hereGET/api/v1/salesshift/webmail/accounts/{account_id}/messagesPaged message overviews from one IMAP folder, with search and filter.Not exercised herePOST/api/v1/salesshift/webmail/accounts/{account_id}/passwordSelf-service mailbox password change.Not exercised hereGET/api/v1/salesshift/webmail/accounts/{account_id}/rawThe original RFC 822 source — "show original" / view-source.Not exercised herePOST/api/v1/salesshift/webmail/accounts/{account_id}/reconnectRe-consent an OAuth mailbox whose refresh token was revoked or expired.Known unprovenGET/api/v1/salesshift/webmail/accounts/{account_id}/reply-contextEverything a composer needs to answer a message: recipients worked out the way Gmail works them out, the ``Re:``/``Fwd:`` subject, the quoted original, and the threading headers.Not exercised hereGET/api/v1/salesshift/webmail/accounts/{account_id}/searchIMAP SEARCH across several folders at once, merged newest-first.Not exercised herePOST/api/v1/salesshift/webmail/accounts/{account_id}/sendSend or save-as-draft a message from a mailbox.Not exercised hereGET/api/v1/salesshift/webmail/accounts/{account_id}/threadFull conversation for a message — the email/reply/email trail, Gmail-style.Not exercised herePOST/api/v1/salesshift/webmail/accounts/provisionCreate a REAL mailbox on the platform mail stack (mailcow + relay spool + inbound sync job) and connect it — the user never touches SOGo.Not exercised herePOST/api/v1/salesshift/webmail/ai/improveRewrite a draft body with the org's AI provider at a chosen tone, language and length.PartialPOST/api/v1/salesshift/webmail/ai/summarize-unreadSummarise up to 15 unread messages with the org's AI provider.PartialGET/api/v1/salesshift/webmail/categoriesThe organization's webmail categories, seeding the defaults on first use.Called livePOST/api/v1/salesshift/webmail/categoriesCreate a webmail category.Not exercised hereDELETE/api/v1/salesshift/webmail/categories/{category_id}Delete a webmail category.Not exercised herePOST/api/v1/salesshift/webmail/oauth/{provider}/connectStart connecting a mailbox — returns the URL to send the user to.Known unprovenGET/api/v1/salesshift/webmail/oauth/callbackWhere the provider sends the browser back.Known unprovenGET/api/v1/salesshift/webmail/oauth/providersWhich mailbox providers this deployment can actually connect.Known unprovenDeals and opportunities
Open reference (11)/api/v1/salesshift/dealsDeals, optionally filtered by pipeline and status.Called livePOST/api/v1/salesshift/dealsCreate a deal, defaulting to the org's first pipeline and stage when none is given.Not exercised herePUT/api/v1/salesshift/deals/{deal_id}Update a deal from a partial payload.Not exercised hereDELETE/api/v1/salesshift/deals/{deal_id}Delete a deal.Not exercised herePUT/api/v1/salesshift/deals/{deal_id}/movePowers drag-and-drop Kanban.Not exercised hereGET/api/v1/salesshift/deals/forecastWeighted pipeline forecast: sum(amount * stage.win_probability).Called liveGET/api/v1/salesshift/opportunitiesOpen, user-posted opportunities; retired platform seed rows are excluded.Called livePOST/api/v1/salesshift/opportunitiesPost an opportunity to the shared board.Not exercised herePOST/api/v1/salesshift/opportunities/{opportunity_id}/applyApply to an open opportunity.Not exercised herePOST/api/v1/salesshift/opportunities/{opportunity_id}/convertOpportunity → lead (contact) → contract (deal) in the default pipeline.Not exercised hereGET/api/v1/salesshift/pipelinesThe organization's deal pipelines and their stages, seeding a default pipeline on first use.Called liveQuotes and products
Open reference (17)/api/v1/salesshift/productsThe organization's product catalogue, searchable and active-filtered.Called livePOST/api/v1/salesshift/productsCreate a catalogue product; recurring products require a billing interval.Verified in sessionPATCH/api/v1/salesshift/products/{product_id}Update a catalogue product from a partial payload.Verified in sessionDELETE/api/v1/salesshift/products/{product_id}Soft delete.Verified in sessionGET/api/v1/salesshift/quotesQuotes, optionally filtered by status and deal.Called livePOST/api/v1/salesshift/quotesCreate a quote with its line items and a generated document number.Verified in sessionGET/api/v1/salesshift/quotes/{quote_id}One quote with its lines and approval history.Called livePATCH/api/v1/salesshift/quotes/{quote_id}Edit a quote; sent, accepted and voided quotes are locked.Verified in sessionDELETE/api/v1/salesshift/quotes/{quote_id}Void a quote; an accepted quote cannot be voided.Verified in sessionPOST/api/v1/salesshift/quotes/{quote_id}/approveApprove a quote that is awaiting approval.Verified in sessionPOST/api/v1/salesshift/quotes/{quote_id}/decline-approvalDecline the pending approval on a quote.Verified in sessionPUT/api/v1/salesshift/quotes/{quote_id}/linesBulk replace — the editor sends the whole grid and the server re-prices it.Verified in sessionPOST/api/v1/salesshift/quotes/{quote_id}/sendFreeze the quote into a contract document, email it, and hand it to the e-sign flow.Verified in sessionPOST/api/v1/salesshift/quotes/{quote_id}/submit-for-approvalSubmit a quote for approval, or approve it outright when no rule is triggered.Verified in sessionGET/api/v1/salesshift/quotes/public/{token}Unauthenticated read for the recipient's link.Verified in sessionGET/api/v1/salesshift/settings/quotesQuote settings for the organization (numbering, tax, approval thresholds).Called livePUT/api/v1/salesshift/settings/quotesSet approval thresholds / reporting currency.Verified in sessionInvoicing and payments
Open reference (22)/api/v1/salesshift/invoicesInvoices, optionally filtered by status.Called livePOST/api/v1/salesshift/invoicesCreate a draft invoice with no quote behind it.Verified in sessionGET/api/v1/salesshift/invoices/{invoice_id}One invoice with its line items.Called livePATCH/api/v1/salesshift/invoices/{invoice_id}Edit the header.Verified in sessionPOST/api/v1/salesshift/invoices/{invoice_id}/checkoutCreate a Stripe Checkout Session for the amount still outstanding.Verified in sessionPOST/api/v1/salesshift/invoices/{invoice_id}/issueDraft → open: stamp the issue date, derive the due date from the payment term and freeze the bill-to snapshot.Verified in sessionPUT/api/v1/salesshift/invoices/{invoice_id}/linesBulk replace, same contract as the quote editor: the client sends the whole grid and the server re-prices it, so a failed call can never leave the document half-updated.Verified in sessionGET/api/v1/salesshift/invoices/{invoice_id}/pdfRender and return the invoice PDF inline.Verified in sessionPOST/api/v1/salesshift/invoices/{invoice_id}/record-paymentBank transfer / cheque / cash.Verified in sessionPOST/api/v1/salesshift/invoices/{invoice_id}/sendEmail the invoice with the PDF attached, from the tenant's own mailbox.Verified in sessionPOST/api/v1/salesshift/invoices/{invoice_id}/voidCancel an invoice that was never paid.Verified in sessionPOST/api/v1/salesshift/invoices/from-quote/{quote_id}Create an invoice from an accepted quote.Verified in sessionGET/api/v1/salesshift/invoices/public/{token}Public invoice view addressed by its share token.Verified in sessionGET/api/v1/salesshift/invoices/public/{token}/pdfThe customer's own copy.Verified in sessionGET/api/v1/salesshift/subscriptionsThe organization's subscriptions, optionally filtered by status.Called livePOST/api/v1/salesshift/subscriptionsCreate a recurring subscription for a contact or company.Not exercised hereGET/api/v1/salesshift/subscriptions/{subscription_id}One subscription by id.Called livePATCH/api/v1/salesshift/subscriptions/{subscription_id}Change the plan value.Not exercised herePOST/api/v1/salesshift/subscriptions/{subscription_id}/cancelCancel a subscription, immediately or at period end.Not exercised herePOST/api/v1/salesshift/subscriptions/{subscription_id}/reactivateReactivate a cancelled subscription.Not exercised hereGET/api/v1/salesshift/subscriptions/mrrThe MRR waterfall — what the ledger exists for.Called livePOST/api/v1/salesshift/webhooks/stripe/{integration_id}Stripe webhook receiver for one payment integration.Verified in sessionContracts and e-sign
Open reference (12)/api/v1/salesshift/contractsThe organization's contract documents, optionally filtered by deal.Called livePOST/api/v1/salesshift/contractsCreate a contract document with its signing parties.Verified in sessionPATCH/api/v1/salesshift/contracts/{contract_id}Edit a contract.Verified in sessionDELETE/api/v1/salesshift/contracts/{contract_id}Void a contract document.Verified in sessionGET/api/v1/salesshift/contracts/{contract_id}/auditThe audit trail behind the Certificate of Completion, for the sender's own dashboard — the same rows the certificate page prints.Called liveGET/api/v1/salesshift/contracts/{contract_id}/pdfThe sender's own copy.Verified in sessionPOST/api/v1/salesshift/contracts/{contract_id}/sendDeliver signing links by real email — and, on a re-send, chase only the party who still owes a signature.Verified in sessionGET/api/v1/salesshift/contracts/sign/{token}Public signing view for a token; records the first open per party as a 'viewed' audit event.Verified in sessionPOST/api/v1/salesshift/contracts/sign/{token}Public signature submit; row-locked so two simultaneous posts cannot both sign.Verified in sessionPOST/api/v1/salesshift/contracts/sign/{token}/declineDecline to sign.Verified in sessionGET/api/v1/salesshift/contracts/sign/{token}/pdfExecuted-contract PDF, rendered by the tenant node's Go e-sign engine (document + signature frames + certificate of completion + audit trail).Verified in sessionPOST/api/v1/salesshift/contracts/uploadBring-your-own contract: upload PDF / DOCX / TXT / MD / HTML — the content is extracted into an editable document that rides the full e-sign flow (edit → send → dual signatures → Go-rendered PDF).Verified in sessionCalendar
Open reference (17)/api/v1/salesshift/calendar/agendaFlat, sorted list of what is coming up — events and bookings together.Called liveGET/api/v1/salesshift/calendar/eventsEverything overlapping [start, end): recurring series expanded into occurrences, detached overrides applied, plus guest bookings.Called livePOST/api/v1/salesshift/calendar/eventsCreate a calendar event, defaulting to the org's default calendar.Verified in sessionGET/api/v1/salesshift/calendar/events/{event_id}One event plus the shape of the series it belongs to.Verified in sessionPATCH/api/v1/salesshift/calendar/events/{event_id}Partial update with Google's recurring-edit scopes.Verified in sessionDELETE/api/v1/salesshift/calendar/events/{event_id}Delete with the same three scopes as the update path.Verified in sessionPOST/api/v1/salesshift/calendar/events/{event_id}/duplicateCopy at the same time with a ' (copy)' suffix.Verified in sessionPOST/api/v1/salesshift/calendar/events/{event_id}/inviteSend or re-send the invitation.Verified in sessionGET/api/v1/salesshift/calendar/events/{event_id}/invitesWho was invited, what they answered, and the two deep links that let the organiser put the same event in their own external calendar.Verified in sessionPOST/api/v1/salesshift/calendar/events/{event_id}/invitesSend or re-send the invitation.Verified in sessionGET/api/v1/salesshift/calendar/export.icsRFC-5545 calendar file.Verified in sessionGET/api/v1/salesshift/calendar/rsvp/{token}The page an attendee lands on from the invitation.Verified in sessionPOST/api/v1/salesshift/calendar/rsvp/{token}Record the reply.Verified in sessionGET/api/v1/salesshift/calendarsThe organization's calendars, seeding a default one when none exist.Called livePOST/api/v1/salesshift/calendarsCreate a calendar; the org's first calendar is always its default.Verified in sessionPATCH/api/v1/salesshift/calendars/{calendar_id}Update a calendar's fields.Verified in sessionDELETE/api/v1/salesshift/calendars/{calendar_id}Events survive — ss_calendar_events.calendar_id is ON DELETE SET NULL.Verified in sessionMessaging and calls
Open reference (57)/api/v1/messaging/attachments/{attachment_id}/fileDownload a message attachment, if the caller is a member of its room.Verified in sessionGET/api/v1/messaging/bookmarksThe caller's saved messages.Called liveGET/api/v1/messaging/calls/{call_id}/intelligenceOne read for the whole post-call record.Known unprovenPOST/api/v1/messaging/calls/{call_id}/recording/chunksAppend one MediaRecorder blob to the in-progress upload.Known unprovenPOST/api/v1/messaging/calls/{call_id}/recording/finalizeSeal the upload into a recording row — IF it was ever announced.Known unprovenGET/api/v1/messaging/calls/{call_id}/recordings/{recording_id}/fileMembership-checked stream.Known unprovenPOST/api/v1/messaging/calls/{call_id}/transcribeFor the common case: the recording landed before anyone configured a key.Known unprovenGET/api/v1/messaging/calls/activeDrives the rooms-rail 'live' pills on first paint, before the lobby socket is up.Called liveGET/api/v1/messaging/chat-invitations/{token}Public lookup of a guest invitation by token.Verified in sessionPOST/api/v1/messaging/chat-invitations/{token}/acceptPublic accept of a guest invitation; provisions the guest user and room membership.Verified in sessionPOST/api/v1/messaging/chat-invitations/{token}/declinePublic decline of a guest invitation.Verified in sessionDELETE/api/v1/messaging/guest-invitations/{invitation_id}Revoke a guest's access.Verified in sessionGET/api/v1/messaging/healthLive health for the messaging plane.Called livePOST/api/v1/messaging/hooks/{token}Post a message into a room from an incoming webhook; the token is the only credential.Verified in sessionGET/api/v1/messaging/invitationsThe caller's pending room invitations.Called livePOST/api/v1/messaging/invitations/{invitation_id}/respondAccept or decline a room invitation.Verified in sessionGET/api/v1/messaging/mentionsThe caller's mention inbox.Called livePOST/api/v1/messaging/mentions/readMark a set of mentions read.Verified in sessionPOST/api/v1/messaging/messages/{message_id}/ackAcknowledge a priority message.Verified in sessionGET/api/v1/messaging/messages/{message_id}/acksWho has acknowledged a message.Verified in sessionPOST/api/v1/messaging/messages/{message_id}/bookmarkSave a message to the caller's bookmarks.Verified in sessionDELETE/api/v1/messaging/messages/{message_id}/bookmarkRemove a message from the caller's bookmarks.Verified in sessionPOST/api/v1/messaging/polls/{poll_id}/voteVote on a poll.Verified in sessionGET/api/v1/messaging/roomsRooms the caller belongs to; guests see only their own rooms.Called livePOST/api/v1/messaging/roomsCreate a chat room; cross-organization rooms are superuser-only and guests may not create rooms.Verified in sessionGET/api/v1/messaging/rooms/{room_id}One room, if the caller is a member.Verified in sessionPOST/api/v1/messaging/rooms/{room_id}/ai`mode='ask'`: posts the question, then VxAI's answer, into the room.PartialPOST/api/v1/messaging/rooms/{room_id}/attachmentsUpload an attachment and create a chat message that references it.Verified in sessionGET/api/v1/messaging/rooms/{room_id}/callThe live call in a room, if there is one.Verified in sessionGET/api/v1/messaging/rooms/{room_id}/callsPast calls in a room.Verified in sessionGET/api/v1/messaging/rooms/{room_id}/guest-invitationsGuest invitations issued for a room.Verified in sessionPOST/api/v1/messaging/rooms/{room_id}/guest-invitationsInvite an external CRM contact into one room as a guest; guests may not invite guests.Verified in sessionPOST/api/v1/messaging/rooms/{room_id}/invitationsInvite a platform user to a room.Verified in sessionPOST/api/v1/messaging/rooms/{room_id}/joinJoin a room.Verified in sessionPOST/api/v1/messaging/rooms/{room_id}/leaveLeave a room.Verified in sessionGET/api/v1/messaging/rooms/{room_id}/messagesMessage history for a room, paged backwards from a timestamp.Verified in sessionPOST/api/v1/messaging/rooms/{room_id}/messagesSend a message via REST API (fallback when WebSocket is not available)Verified in sessionPUT/api/v1/messaging/rooms/{room_id}/messages/{message_id}Edit your own message.Verified in sessionDELETE/api/v1/messaging/rooms/{room_id}/messages/{message_id}Soft-delete a single message ("delete for everyone").Verified in sessionPOST/api/v1/messaging/rooms/{room_id}/messages/{message_id}/forwardForward to up to 5 rooms the caller belongs to (WhatsApp's anti-spam cap).Verified in sessionPOST/api/v1/messaging/rooms/{room_id}/messages/{message_id}/pinPin or unpin a message in a room.Verified in sessionGET/api/v1/messaging/rooms/{room_id}/messages/{root_id}/threadRoot message + its replies, oldest first.Verified in sessionGET/api/v1/messaging/rooms/{room_id}/messages/searchServer-side search over the FULL room history.Verified in sessionGET/api/v1/messaging/rooms/{room_id}/pinsPinned messages in a room.Verified in sessionGET/api/v1/messaging/rooms/{room_id}/pollsPoll snapshots for a room.Verified in sessionPOST/api/v1/messaging/rooms/{room_id}/pollsCreate a poll in a room (question plus 2-12 options).Verified in sessionPOST/api/v1/messaging/rooms/{room_id}/readRecord read receipts for every message from other senders in this room that the caller hasn't read yet, and broadcast so senders' ticks update.Verified in sessionPOST/api/v1/messaging/rooms/{room_id}/scheduledSchedule a message to be posted to a room later.Verified in sessionGET/api/v1/messaging/rooms/{room_id}/settingsReturn the caller's per-room flags (mute/favorite/blocked/etc.).Verified in sessionPUT/api/v1/messaging/rooms/{room_id}/settingsPersist the caller's per-room flags.Verified in sessionGET/api/v1/messaging/rooms/{room_id}/usersRoom participants with their presence state.Verified in sessionPOST/api/v1/messaging/rooms/{room_id}/webhookReturns a tokenized URL that external systems (CI, Grafana, vxalerts) can POST {"text": "..."} to.Verified in sessionGET/api/v1/messaging/rooms/discoverList joinable rooms the caller isn't in yet — for the Browse Channels / Browse Groups UI.Called liveGET/api/v1/messaging/rtc/iceSTUN/TURN config + the mesh caps the server will actually enforce.Called liveGET/api/v1/messaging/scheduledThe caller's scheduled messages.Called liveDELETE/api/v1/messaging/scheduled/{scheduled_id}Cancel one of the caller's scheduled messages.Verified in sessionGET/api/v1/messaging/usersList active users available to start a direct message with.Called liveMarketing
Open reference (17)/api/v1/salesshift/automationsThe organization's automation rules.Called livePOST/api/v1/salesshift/automationsCreate an automation rule from a known trigger and action pair.Not exercised herePUT/api/v1/salesshift/automations/{rule_id}Update an automation rule.Not exercised hereDELETE/api/v1/salesshift/automations/{rule_id}Delete an automation rule.Not exercised hereGET/api/v1/salesshift/booking-linksThe organization's booking links and their booking counts.Called livePOST/api/v1/salesshift/booking-linksCreate a booking link owned by the calling user.Not exercised hereGET/api/v1/salesshift/formsThe organization's lead-capture forms.Called livePOST/api/v1/salesshift/formsCreate a lead-capture form; the field set must include an email field.Not exercised hereDELETE/api/v1/salesshift/forms/{form_id}Delete a form.Not exercised hereGET/api/v1/salesshift/pagesThe organization's landing pages.Called livePOST/api/v1/salesshift/pagesCreate a landing page with a slug derived from its name.Not exercised hereDELETE/api/v1/salesshift/pages/{page_id}Delete a landing page.Not exercised hereGET/api/v1/salesshift/public/book/{slug}Public HTML booking page for an active link.Not exercised herePOST/api/v1/salesshift/public/book/{slug}Public booking submit; records the booking and returns an HTML confirmation.Not exercised hereGET/api/v1/salesshift/public/forms/{form_id}Public HTML render of an active form.Called livePOST/api/v1/salesshift/public/forms/{form_id}/submitPublic form submit; creates a submission and an HTML confirmation.Not exercised hereGET/api/v1/salesshift/public/p/{slug}Public HTML render of a published landing page by slug.Not exercised here/api/v1/salesshift/seo/auditCrawl + analyse a site on the tenant node, store the result, notify.Not exercised hereGET/api/v1/salesshift/seo/auditsAudit history — summary rows only unless ``?full=1``.Called liveGET/api/v1/salesshift/seo/audits/{audit_id}One SEO audit with its full findings.Called liveGET/api/v1/salesshift/seo/keywordsTracked keywords, optionally narrowed to one site.Called livePOST/api/v1/salesshift/seo/keywordsBulk-add tracked keywords (deduped against what's already tracked).Not exercised hereDELETE/api/v1/salesshift/seo/keywords/{keyword_id}Stop tracking a keyword.Not exercised herePOST/api/v1/salesshift/seo/keywords/{keyword_id}/checkReal SERP position check through the node engine, then persist it.Not exercised herePOST/api/v1/salesshift/seo/keywords/check-allSequentially re-check up to 25 tracked keywords (small delay between SERP fetches).Not exercised hereGET/api/v1/salesshift/seo/overviewRollup across the org's sites, keywords and audits.Called liveGET/api/v1/salesshift/seo/sitesThe organization's tracked sites with their keyword counts.Called livePOST/api/v1/salesshift/seo/sitesAdd a site to track, normalising and validating the domain.Not exercised hereDELETE/api/v1/salesshift/seo/sites/{site_id}Removes the site and — via ON DELETE CASCADE — its keywords, rank history and audit history.Not exercised herePOST/api/v1/salesshift/seo/suggestReal Google autocomplete suggestions via the node — no invented ideas.Not exercised hereWorkflows
Open reference (14)/api/v1/salesshift/workflow-runs/{run_id}One workflow run with its per-node step log.Not exercised hereGET/api/v1/salesshift/workflowsThe organization's workflows, optionally filtered by status.Called livePOST/api/v1/salesshift/workflowsCreate a workflow with a validated status and trigger type.Not exercised hereGET/api/v1/salesshift/workflows/{workflow_id}One workflow with its run count.Called livePUT/api/v1/salesshift/workflows/{workflow_id}Update a workflow from a partial payload.Not exercised hereDELETE/api/v1/salesshift/workflows/{workflow_id}Delete a workflow.Not exercised herePOST/api/v1/salesshift/workflows/{workflow_id}/activateActivate — but only a graph the engine says is valid goes live.Not exercised herePOST/api/v1/salesshift/workflows/{workflow_id}/duplicateCopy a workflow, its nodes and its edges into a new draft.Not exercised herePOST/api/v1/salesshift/workflows/{workflow_id}/enrollOne run per contact.Not exercised herePOST/api/v1/salesshift/workflows/{workflow_id}/pauseSet a workflow's status to paused.Not exercised hereGET/api/v1/salesshift/workflows/{workflow_id}/runsRecent runs of one workflow.Not exercised herePOST/api/v1/salesshift/workflows/{workflow_id}/test-runRun the graph once and hand back the full trace for the canvas.Not exercised herePOST/api/v1/salesshift/workflows/{workflow_id}/validateProxy the node's graph linter.Not exercised herePOST/api/v1/salesshift/workflows/internal/actionPerform one side-effecting node on behalf of the Go engine.Not exercised hereReports and analytics
Open reference (36)/api/v1/salesshift/analytics/activity/healthIs the projection actually keeping up, and what is it missing?Not exercised hereGET/api/v1/salesshift/analytics/activity/timelineOrdered event history for a contact, a workflow, a run, or the whole org.Not exercised hereGET/api/v1/salesshift/analytics/attributionCredit won-deal revenue across the touches that preceded it.Called livePOST/api/v1/salesshift/analytics/attribution/backfillBackfill attribution touches for the organization.Not exercised hereGET/api/v1/salesshift/analytics/campaign-performancePer-campaign engagement: opened/replied come from ss_email_tracking.Not exercised hereGET/api/v1/salesshift/analytics/contract-cycleE-sign cycle: status counts, avg hours sent→completed, last 5 contracts.Not exercised hereGET/api/v1/salesshift/analytics/emailSent/opened/clicked/replied/bounced counts from the email tracking table.Called liveGET/api/v1/salesshift/analytics/engagementReply-category breakdown + top 10 engaged contacts (opens + 5x replies).Not exercised hereGET/api/v1/salesshift/analytics/funnelDeal pipeline funnel: stages in display_order with OPEN deal count, value and each stage's share of the first stage (deals sit in their CURRENT stage).Not exercised hereGET/api/v1/salesshift/analytics/overviewONE aggregate powering the Overview dashboard — every number is real SQL.Called liveGET/api/v1/salesshift/analytics/pipeline-historyWhat the funnel looked like over time — the question fixed dashboards could never answer.Called livePOST/api/v1/salesshift/analytics/pipeline-snapshot/runTake a pipeline snapshot immediately instead of waiting for the scheduled run.Not exercised hereGET/api/v1/salesshift/analytics/salesWin/loss counts and pipeline value aggregated from the org's deals.Called liveGET/api/v1/salesshift/analytics/timeseriesPer-day sent/opened/replied counts.Not exercised hereGET/api/v1/salesshift/dashboardsThe organization's dashboards.Called livePOST/api/v1/salesshift/dashboardsCreate a dashboard owned by the calling user.Not exercised hereGET/api/v1/salesshift/dashboards/{dashboard_id}One dashboard with its widgets.Not exercised herePOST/api/v1/salesshift/dashboards/{dashboard_id}/widgetsAdd a widget backed by a saved report to a dashboard.Not exercised hereDELETE/api/v1/salesshift/dashboards/widgets/{widget_id}Remove a widget from a dashboard.Not exercised herePATCH/api/v1/salesshift/deals/{deal_id}/forecast-categorySet a deal's forecast category (commit, best case, pipeline, omitted).Not exercised hereGET/api/v1/salesshift/emailsInbox feed — every tracked outbound email with its engagement state.Called liveGET/api/v1/salesshift/forecastCategory roll-up from live deals, plus every submission for the period so called-vs-actual is visible rather than lost.Called livePOST/api/v1/salesshift/forecast/submitAppend a submission.Not exercised hereGET/api/v1/salesshift/goalsThe organization's goals.Called livePOST/api/v1/salesshift/goalsCreate a goal against a known metric.Not exercised hereGET/api/v1/salesshift/goals/leaderboardAttainment per owner: actuals from the same data the reports use, goals from ss_goals, sorted by percentage of target.Not exercised hereGET/api/v1/salesshift/reportsThe organization's saved reports.Called livePOST/api/v1/salesshift/reportsSave a report; the definition is compiled and run first, so an unrunnable report is never stored.Called liveGET/api/v1/salesshift/reports/{report_id}One saved report, executed by default.Called livePATCH/api/v1/salesshift/reports/{report_id}Update a saved report's name or definition.Not exercised hereDELETE/api/v1/salesshift/reports/{report_id}Delete a report along with its dashboard widgets and schedules.Called liveGET/api/v1/salesshift/reports/{report_id}/exportRun a saved report and return it as a downloadable file.Called livePOST/api/v1/salesshift/reports/{report_id}/scheduleSchedule recurring delivery of a saved report.Not exercised hereGET/api/v1/salesshift/reports/{report_id}/schedulesThe delivery schedules attached to one report.Not exercised hereGET/api/v1/salesshift/reports/datasetsWhat the builder UI renders.Called livePOST/api/v1/salesshift/reports/runRun a report definition without saving it.Called liveSettings and team
Open reference (16)/api/v1/salesshift/settings/dns-checkCheck SPF / DMARC TXT records for a sending domain (DKIM needs the selector, so it reports 'unknown' unless one is provided).Not exercised hereGET/api/v1/salesshift/settings/integrationsThe organization's configured integrations (email, AI, payment providers).Called livePOST/api/v1/salesshift/settings/integrationsStore credentials in Vault and upsert the metadata row.Not exercised hereDELETE/api/v1/salesshift/settings/integrations/{integration_id}Delete one integration.Not exercised herePOST/api/v1/salesshift/settings/integrations/{integration_id}/testRead the credentials back out of Vault and use them against the provider for real — a Vault round-trip alone proves nothing about whether the key, host, port or password still work.Not exercised hereGET/api/v1/salesshift/settings/mailboxesThe organization's configured sending mailboxes.Called livePOST/api/v1/salesshift/settings/mailboxesRegister a sending mailbox for the organization.Not exercised herePOST/api/v1/salesshift/settings/poll-replies-nowManually run one IMAP reply-detection pass (the background loop also runs this every ~5 minutes).Not exercised hereGET/api/v1/salesshift/settings/suppressionsUp to 500 suppressed addresses for the organization.Called livePOST/api/v1/salesshift/settings/suppressionsAdd an address to the organization's suppression list.Not exercised hereDELETE/api/v1/salesshift/settings/suppressions/{suppression_id}Release an address.Not exercised hereGET/api/v1/salesshift/settings/teamEvery user of the current organization (active and deactivated).Called livePATCH/api/v1/salesshift/settings/team/{user_id}Change a teammate's role, or bring a deactivated one back.Not exercised hereDELETE/api/v1/salesshift/settings/team/{user_id}Deactivate a teammate; admin only, and the caller cannot deactivate themselves.Not exercised herePOST/api/v1/salesshift/settings/team/inviteCreate a teammate account in THIS org via the shared tenant-user creator, then email them their credentials.Not exercised hereGET/api/v1/salesshift/statsDashboard counters: contacts, companies, open deals, active sequences and the email funnel.Called livePlans and your subscription
Open reference (16)/api/v1/salesshift/billing/activatePut this workspace on a free plan.Called livePOST/api/v1/salesshift/billing/cancelCancel the Stripe subscription, at period end or immediately.PartialPOST/api/v1/salesshift/billing/changeMove to another paid plan, change the seat count, or both.PartialPOST/api/v1/salesshift/billing/checkoutStart a Stripe Checkout session for a paid plan at a given seat count.PartialPOST/api/v1/salesshift/billing/checkout/confirmCalled by the browser when Stripe redirects back.Not exercised hereGET/api/v1/salesshift/billing/entitlementsWhat this workspace may do, without the billing detail.Called liveGET/api/v1/salesshift/billing/eventsThe workspace's platform-billing event log, newest first.Called liveGET/api/v1/salesshift/billing/invoicesStripe is the ledger; we do not keep a shadow copy to drift out of date.PartialGET/api/v1/salesshift/billing/plansThe published plans, what each includes, and whether it is bought or activated.Called livePOST/api/v1/salesshift/billing/portalCard changes, cancellation and receipts are Stripe's hosted portal.PartialPOST/api/v1/salesshift/billing/resumeUndo a cancellation that has not taken effect yet.PartialGET/api/v1/salesshift/billing/self-hostedWhether this workspace has a registered node, and the identity a node must report to become one.Called livePOST/api/v1/salesshift/billing/self-hosted/nodeRegister the tenant's own node, after the node proves whose it is.Called liveDELETE/api/v1/salesshift/billing/self-hosted/nodeDetach the node.Called liveGET/api/v1/salesshift/billing/subscriptionThis workspace's own subscription: plan, seats, period, members and the entitlements it resolves to.Called livePOST/api/v1/salesshift/billing/webhookUnauthenticated by design — the signature IS the authentication.PartialWebhooks and tracking
Open reference (7)/api/v1/salesshift/t/c/{tracking_id}Public click tracker; records the click then redirects to the http(s) destination.Not exercised hereGET/api/v1/salesshift/t/o/{tracking_id}.pngPublic 1x1 tracking pixel; records an open against the tracking id.Not exercised hereGET/api/v1/salesshift/u/{tracking_id}Public unsubscribe confirmation page for a tracking id.Not exercised herePOST/api/v1/salesshift/u/{tracking_id}Public unsubscribe submit; suppresses the address and returns an HTML confirmation.Not exercised herePOST/api/v1/salesshift/webhooks/{integration_id}/mailgunMailgun webhook — {'event-data': {...}} payload.Not exercised herePOST/api/v1/salesshift/webhooks/{integration_id}/sendgridSendGrid Event Webhook — JSON array of events.Not exercised herePOST/api/v1/salesshift/webhooks/{integration_id}/sesAWS SES via SNS.Not exercised hereThese pages are generated from app/docs/_inventory.json, last updated on 2026-08-13 and produced by importing the live router objects and walking them, then calling 110 of the routes against a running server — 92 of them in the first pass against http://127.0.0.1:8741, the rest in the later passes the file records. The same file backs endpoints.json and llms.txt.