Documentation

SalesFlow CRM

How the application works, what each feature does, and the full HTTP API reference. Use the sidebar to jump to a topic, or search it to find one.

Getting started

Introduction

SalesFlow is a CRM for capturing leads, working them through a pipeline, and reporting on the result.

SalesFlow gives a sales team one place to keep every lead, every deal and every conversation. Leads arrive from your website, an import or manual entry; your team qualifies them, records calls and emails against them, and moves the resulting deals through a pipeline you define. Dashboards and reports then show how the pipeline is performing.

What you get

Contacts
A searchable, filterable database of every lead, with assignment, statuses, stages, activity history and per-contact follow-ups.
Deals
Revenue opportunities linked to a contact, moved through pipeline stages you can rename and reorder.
Projects
Named lead sources that route incoming website submissions to specific people.
Team
Invite colleagues, set their role, and assign leads to them.
Reports & dashboards
Overview metrics, sales performance, lead analytics and an admin view of organization-wide activity.
Integrations
Gmail for sending email, Twilio for voice calls, an external database sync, and a public endpoint for website forms.
Resources
Files you have emailed to contacts, kept and searchable so they can be re-sent.

Terminology may differ in your workspace

Administrators can rename Deal and Deals to whatever your business calls them. This documentation uses the default names.

Core concepts

Four ideas explain most of how the app behaves.

Organization
Your workspace. All contacts, deals, settings and files belong to one organization, and data is never shared between organizations. You can belong to more than one and switch between them from the sidebar.
Role
Every member is either an Admin or a Member. The role decides which pages and actions are available.
Plan
Your subscription decides how many records you can store, which features are unlocked, and how many people you can invite.
Assignment
A contact can be assigned to one team member, who becomes its owner. Depending on a setting, members may see only the leads assigned to them.

Switching organizations resets your view

When you switch to another organization the app reloads and clears the search term and filters on Contacts and Deals, so you never see one workspace's filters applied to another's data. Column layout preferences are kept.

Signing in and organizations

  1. 1Sign up or log in from the landing page.
  2. 2Choose an organization. If you do not belong to one yet, you are prompted to create one — that becomes your workspace.
  3. 3Use the organization switcher in the sidebar to move between workspaces or to create another one.
  4. 4New organizations start on a 14-day free trial with full access.

When the trial ends

If the trial expires without a subscription, the CRM is locked until you subscribe. Billing pages stay accessible so you can pick a plan and continue where you left off.

The sidebar is the primary navigation. It can be minimized to icons only on desktop and collapses into a menu button on mobile. It also holds the theme toggle, the notification bell and the organization switcher.

PageWhat it is for
DashboardHeadline metrics, pipeline snapshot, recent leads and upcoming follow-ups
ContactsThe full lead database with search, filters, bulk actions and export
DealsPipeline value summary and the full deal list
TeamMembers, roles, invitations and lead assignments
ProjectsNamed lead sources for routing website submissions
IntegrationsConnect Gmail, Twilio, an external database and your website form
ReportsOverview, sales performance, lead analytics and calling reports
BillingYour plan, usage and subscription
SettingsTerminology, stages, statuses, custom fields, currency and visibility
ResourcesFiles previously emailed to contacts
AdminOrganization-wide statistics, trends and activity (admins only)

Install as an app

SalesFlow can be installed to your desktop or home screen from the browser's install prompt. Installed, it opens in its own window and keeps you signed in.

Light and dark mode

Use the theme toggle in the sidebar to switch between light and dark. Your choice is remembered on that device.

Leads and pipeline

Contacts

The contact list is where most day-to-day work happens.

Adding contacts

Add Contact
The full form, with every standard field plus any custom fields your administrator has defined.
Quick Add
An inline row at the top of the table for entering a lead without leaving the list.
Contact + Deal
Creates a contact and, in the same flow, an optional first deal for them.
Import
Bulk-create contacts from a file. Available to administrators.
Website form
Submissions from your site arrive automatically once the form integration is set up.

Fields on a contact

FieldNotes
Name, email, phoneRequired. Email and phone must be unique within the organization.
CompanyOptional.
Lead scoreA number from 0 to 100 you can use to rank leads.
StatusCold, warm or hot by default — administrators can replace these with their own set.
StagePre-sales progress: Not Contacted, No Response, Follow Up or Connected.
SourceWhere the lead came from, such as Referral, Website Form, Social Media or Import.
Campaign detailsUTM source, medium, campaign, term and content, plus the page and form the lead submitted.
CommentFree text notes.
Custom fieldsAny additional fields your administrator has configured.

Working the list

  • Search by name, company, email or phone.
  • Build filters row by row — pick a field, choose Is or Is not, then pick a value. Add as many rows as you need.
  • Filter by status, assignment, assigned member, month, source, stage, or whether the contact has any deals.
  • Choose how many rows per page, from 10 up to 100.
  • Show, hide, reorder and resize columns; the layout is remembered per device.
  • Select rows with the checkboxes to delete in bulk (administrators and members with delete permission).
  • Export the results — see Exporting data.

Your search and filters are remembered

Filters, the search term, page size and column layout persist as you navigate away and come back, and across a browser refresh.

Keyboard shortcuts

ShortcutAction
Ctrl + NQuick add a contact
Ctrl + DCreate a contact and a deal together
Ctrl + FFocus the search box

Contact details and activity

Opening a contact shows its full profile alongside everything that has happened to it.

Profile
All standard and custom field values, the assigned owner, and when the record was created and last updated.
Activity timeline
An audit trail of what changed and who changed it — creations, updates with the specific fields that changed, deletions, assignment and unassignment, and new enquiries.
Enquiries
Later form submissions that matched this same person. The profile keeps the original record; each repeat submission is listed here with its own details and timestamp.
Related deals
Every deal linked to this contact, with quick access to open or edit them.
Follow-ups
Scheduled reminders for this contact.
Quick actions
Call or email the contact, create a deal, or edit the record.

Follow-ups

A follow-up is a dated reminder with a message, attached to a contact. Schedule one from the contact's page, and it appears on your dashboard as it comes due.

StatusMeaning
PendingScheduled and not yet due
SentThe reminder has gone out
CompletedYou marked the follow-up as done
CancelledYou cancelled it before it was due
FailedThe reminder could not be delivered

The dashboard shows upcoming follow-ups and recently processed ones, so nothing quietly slips past its date.

Deals

A deal is a revenue opportunity attached to a contact. Every deal has a title, a value, a stage, a probability and an open date, plus optional description, comment, close date and custom fields.

Default stages

  • Prospecting
  • Proposal
  • Qualification
  • Closing
  • Won
  • Lost

Administrators can replace these with their own stages, each with its own label, colour, default probability and order, and can mark which stages count as won and which as lost.

The deals list

  • Summary cards show open pipeline value, won value, won count and the number of active deals.
  • Search by title, and filter by stage or by month.
  • Show, hide, reorder and resize columns, and set the page size.
  • Values are shown in your organization's currency.
  • Export the results — see Exporting data.

Projects and lead routing

A project is a named lead source — a landing page, a campaign, a microsite. Each project has a slug, and when a website submission includes that slug the new lead is routed to the people assigned to the project.

  1. 1Create a project and give it a name and a slug such as summer-lp-2026.
  2. 2Assign one or more team members to it.
  3. 3Include the slug in your website form submission.
  4. 4New leads from that form are attributed to the project and routed to its assignees.

The Projects page also gives you a ready-made snippet to embed, and projects can be archived when a campaign ends.

Team and access

Roles and permissions

Every member is either an Admin or a Member.

Permissions are fixed per role. Admins have the full set; members have a working subset that excludes destructive and configuration actions.

CapabilityAdminMember
View contactsYesYes
Create and edit contactsYesYes
Delete contactsYesNo
View dealsYesYes
Create and edit dealsYesYes
Delete dealsYesNo
View reportsYesYes
View settingsYesYes
Change settingsYesNo
View teamYesYes
Invite members and assign leadsYesNo
Place and view callsYesYes
Send emailYesYes
View revenueYesNo
Admin dashboardYesNo
Bulk import contactsYesNo

Actions you do not have permission for are hidden rather than shown disabled, so your view of the app matches what you can actually do.

Team management

The Team page is organized into four tabs.

Overview
Total members, active assignments, your current plan and recent activity.
Team Members
Everyone in the organization with their role, plus invitations for new members.
Lead Assignments
Who owns which leads, and the ability to reassign.
Settings
Organization-level details.

The number of people you can invite is limited by your plan. If you are at the seat limit, the invitation is blocked with a prompt to upgrade.

Lead assignment and visibility

Assigning a contact gives it an owner. Administrators choose how visible unassigned and other people's leads are, using the lead visibility setting.

ModeWhat members see
OpenEvery lead in the organization
RestrictedOnly the leads assigned to them

Administrators always see every lead regardless of the mode. The setting also applies to exports, so a member's export contains only what they can see.

Insights and alerts

Dashboard

The dashboard is the landing page after signing in.

Metric cards
Total leads, active deals, revenue and conversion rate.
Pipeline
Deals grouped by stage so you can see where value is sitting.
Recent leads
The newest contacts, with quick access to open them.
Follow-ups
What is due next and what was recently processed.

Reports

Reports are grouped into four views, each of which can be narrowed to the current month, last month, the last three months or the last six months.

Overview
Headline performance across leads and deals.
Sales Performance
Deal value, win rates and pipeline movement.
Lead Analytics
Where leads come from and how they convert.
AI Calling Report
Outcomes from automated calling.

Reports can be exported to PDF or Excel where your plan allows.

Admin dashboard

Administrators get an organization-wide view that ordinary members do not see.

  • Totals for contacts, deals and calls.
  • Deals broken down by stage and contacts by status.
  • Trends over time.
  • Member behaviour analytics — who created the most contacts, the most deals and made the most calls.
  • Top performers and most active users.
  • A live activity stream of what is happening across the organization.

Notifications and live updates

The bell in the sidebar shows unread notifications. Open it for the full list, mark items as read, or delete them.

NotificationRaised when
Lead createdA new contact is added to the organization
Lead assignedA contact is assigned to you
Lead enquiryAn existing contact submits your form again
Deal updatedA deal you are involved with changes
Task assignedWork is assigned to you

Live updates

Open pages update themselves as data changes elsewhere. If a colleague adds a lead or moves a deal, your contacts, deals, notifications, settings and integration status refresh without a manual reload.

Working with your data

Search and filtering

Contacts and Deals share the same filter bar. Search matches as you type, and filters are built as rows.

  1. 1Open Filters and choose Add filter.
  2. 2Pick the field to filter on.
  3. 3Choose Is to include matches, or Is not to exclude them.
  4. 4Pick the value.
  5. 5Add more rows to narrow further — all rows must match.
  6. 6Use Clear filters to start again.

A dot on the Filters button tells you filters are currently applied.

Exporting data

Export what you are looking at, or the whole database — in Excel, PDF or Word.

The Export button on Contacts and Deals opens a dialog where you choose what to export and in which format.

Choosing what to export

Export all
Every record in the organization, across all pages — not just the page you are looking at.
Export filtered
Only the records matching your current search and filters, across all pages. Available once a search term or filter is applied.

Choosing a format

FormatFile
ExcelA .xlsx spreadsheet with one row per record
PDFA landscape .pdf table
DocumentA .docx document containing the same table

The dialog shows progress while records are gathered, and the finished file is named after the scope you chose. Very large exports are capped at 20,000 records; if that happens you are told, and narrowing your filters lets you export the rest.

Exports respect your permissions. If lead visibility is restricted, a member's export contains only the leads assigned to them.

Importing contacts

Administrators can import many contacts at once from the Import button on the Contacts page. Each row is validated the same way the contact form is, so bad rows are reported rather than silently dropped.

After an import you are shown how many records succeeded, how many failed, and why each failure was rejected. Duplicate emails or phone numbers are reported as duplicates rather than creating a second record.

Resources

Every file you email to a contact is kept in Resources, together with who it went to, the subject it was sent with and when it was last sent. Search the list, open a resource to see its details, and re-send it without hunting for the original file.

How many resources you can keep, and the maximum size of each file, depend on your plan.

Integrations

Overview

The Integrations page connects SalesFlow to the tools around it. Each integration shows a status badge so you can see at a glance whether it is connected, and usage statistics where relevant.

IntegrationWhat it enables
Google (Gmail)Send email to contacts from your own Gmail account
Twilio VoicePlace calls to contacts from the browser, with recording and call status
External database (MySQL)Push deal data to a database you control
API calls on won dealsPOST to any API when a deal is won
Website contact formReceive leads submitted on your own site

Only administrators can connect or change integrations. Members can see connection status.

Gmail

  1. 1Open Integrations and choose to connect Google.
  2. 2Sign in to the Google account you want to send from and grant access.
  3. 3The card switches to connected, and email actions across the app start using that account.

Usage statistics show how many emails were sent today, this month and in total. Your plan sets a monthly email allowance.

Twilio Voice

With Twilio connected, the call button on a contact dials from your browser. There is a test action on the integration card to confirm the configuration works before you rely on it.

  • Place calls to contacts without leaving the app.
  • Track call status while the call is in progress.
  • Keep call recordings against the contact.
  • See calls made today and in total on the integration card.

External database sync

If you keep a system of record outside the CRM, this integration writes deal data into a MySQL table you nominate. You choose when it fires — either only when a deal is won, or on every deal update — and you map each column in your table to a field on the deal.

A test action verifies the connection and the mapping before you enable it.

API calls on won deals

Set up any number of API calls that fire automatically when one of your deals moves into a won stage. Each call is a POST request with its own endpoint, headers and JSON body, so you can notify a billing system, an order pipeline and a chat relay from the same event.

  1. 1Open Integrations and configure API calls on won deals.
  2. 2Add a call and give it a name so you can recognise it later.
  3. 3Enter the https endpoint URL it should POST to.
  4. 4Add any headers the receiver needs, such as an Authorization token.
  5. 5Write the JSON body, using placeholders for deal and contact values.
  6. 6Send a test delivery to confirm the receiver accepts it, then save.

Placeholders

Anything in double braces is replaced with a value from the won deal or its contact. A placeholder inside quotes becomes text; one on its own becomes a number, so amounts stay numeric.

A request body
{
  "customer": "{{contact.name}}",
  "email": "{{contact.email}}",
  "deal": "{{deal.title}}",
  "amount": {{deal.value}}
}

Available placeholders are deal.title, deal.value, deal.stage, deal.probability, deal.description, deal.comment, deal.openDate, deal.closeDate, contact.name, contact.email, contact.phone and contact.company.

Delivery

  • Every enabled call fires at the same time when a deal reaches a won stage.
  • Content-Type is set to application/json for you.
  • A call that times out after 10 seconds, or returns 429 or a 5xx, is retried twice with a short pause.
  • Other error responses are not retried, since repeating them would not help.
  • Failures do not block or undo the deal update.

What the test sends

Send test posts sample values rather than a real customer record, so you can verify a new endpoint without sending anyone's data to it.

Endpoints must be public https

Requests come from our servers, so the URL has to be an https address reachable from the internet. Private and internal addresses are rejected.

Header values are write-only

Once saved, header values are never shown again — the field reads Saved and stays blank until you type a replacement. Saving without touching it keeps the stored value.

Website lead capture

Your website can post form submissions straight into Contacts. The Integrations page gives you the endpoint, your form secret and a ready-to-run example, and the API reference documents the request in full.

  • Submissions create a new contact, or attach an enquiry to the matching existing contact.
  • Campaign details such as UTM parameters, the page title and the form title are captured alongside the lead.
  • Including a project slug routes the lead to that project's assignees.
  • Team members are notified when a lead arrives.

Keep your form secret private

The secret authorizes writing leads into your organization. Send it from your server or your form handler, and rotate it from Integrations if it is ever exposed.

AI calling

AI calling places automated calls to leads with live transcription and scoring, and reports on the outcome. It is part of the top plan; some capabilities are marked as coming soon in the interface while they are being finished.

Customizing the workspace

Terminology

If your business does not call them deals, rename them. Set your own singular and plural labels and they replace Deal and Deals everywhere — in the sidebar, buttons, tooltips, forms, dialogs and exports.

Stages and statuses

Custom deal stages

Replace the default pipeline with your own stages. Each stage has a label, an optional colour, a default probability and a position in the order, and you mark which stages mean won and which mean lost so reporting stays accurate.

Custom contact statuses

Replace cold, warm and hot with the statuses your team actually uses. Each has a label, an optional colour and a position.

Custom fields

Add fields of your own to contacts and to deals. Custom fields appear on the relevant forms, can be shown as columns in the table, are included in exports, and can be sent through the website form integration.

Field typeUse for
TextFree-form values
NumberCounts and quantities
CurrencyMonetary amounts
DateDates
BooleanYes or no
SelectA fixed list of options you define
ArrayMultiple values
ObjectGrouped, nested fields

How many custom fields you can define depends on your plan. Adding or removing a field updates the table column list automatically.

Currency and visibility

Choose the currency monetary values are displayed in — US Dollar or Indian Rupee. The choice applies across deals, dashboards, reports and exports.

Lead visibility decides whether members see every lead or only the ones assigned to them. See Lead assignment and visibility.

Plans and billing

Plans and limits

The Billing page shows your current plan, what it includes and your usage against it. Limits are enforced as you work: when you reach one, the action is blocked with a message telling you which limit you hit and which plan lifts it.

LimitFreeStarterPro
Contacts100500Unlimited
Deals50250Unlimited
Projects210Unlimited
Resources210Unlimited
Follow-ups550Unlimited
Emails per month10200Unlimited
Custom fieldsNone5Unlimited
Resource file size5 MB25 MB100 MB
Seats1Per planPer plan

Plan names, prices and the exact feature list come from your billing configuration and are shown on the Billing page. The table above covers the usage caps.

Free trial

New organizations get a 14-day free trial with full access and no card required. A banner counts down the days remaining. When the trial ends, CRM features are locked until you subscribe; the Billing pages stay open so you can choose a plan, and your data is waiting when you do.

Feature access

Some features belong to specific plans. Where a feature is not included in yours, the interface shows it behind an upgrade prompt rather than hiding it, so you can see what a higher plan adds.

SituationWhat you see
You hit a usage capA message naming the limit and the plan that raises it
The feature is not on your planAn upgrade prompt in place of the feature
You are at your seat limitInvitations are blocked with a prompt to upgrade
The feature is announced but not yet shippedIt is marked as coming soon
Your trial has endedA lock screen with a link to subscribe

API reference

Overview

Everything the application does is available over a JSON HTTP API.

All endpoints live under /api on your own SalesFlow domain. Requests and responses are JSON unless noted, and every endpoint operates inside the organization you are signed in to — you never pass an organization identifier yourself.

Authentication

Session
The default. The signed-in user's session is used, and the endpoint applies that user's role and permissions. This is how the application itself calls the API.
Form secret
Used only by the public lead capture endpoint. Your website sends an x-contact-secret header instead of a session.

Permissions apply to the API, not just the interface

Where an endpoint lists a required permission, calling it as a user who lacks that permission returns 403 — the same rules that hide a button also block the request.

Conventions

ConventionDetail
Content typeapplication/json, except file upload endpoints which accept multipart/form-data
IdentifiersRecord ids are opaque strings; always pass back exactly what you received
DatesISO 8601 strings in responses
Pagingpage and limit query parameters; responses include totalPages and currentPage
FilteringA filters query parameter containing a JSON array of filter rows

Filter rows

List endpoints that support filtering accept the same structure the filter bar produces. Each row names a field, an operator and a value, and all rows must match.

The filters query parameter, before URL encoding
[
  { "field": "status", "operator": "is", "value": "hot" },
  { "field": "source", "operator": "is not", "value": "Import" }
]

Errors

Errors return a non-2xx status and a JSON body with a human-readable message. Validation failures include the specific problem so it can be shown next to the offending field.

StatusMeaning
400The request was malformed or failed validation
401Not signed in, or the form secret was missing or wrong
403Signed in, but not allowed — a permission, a plan limit or an expired trial
404The record does not exist in your organization
409A record with that email or phone number already exists
429Too many form submissions from the same lead in a short window
500Something went wrong on the server

Plan and trial responses

When a request is refused for subscription reasons the 403 body carries a code so the interface can show the right prompt.

CodeRaised when
PLAN_LIMITA usage cap such as contacts or deals has been reached
FEATURE_GATEDThe feature is not part of the current plan
SEAT_LIMITThe organization has no seats left for another member
FEATURE_COMING_SOONThe feature is entitled but not yet available
FREE_TRIAL_EXPIREDThe free trial has ended and no subscription is active
A plan limit response
{
  "code": "PLAN_LIMIT",
  "message": "You have reached the contact limit for your plan.",
  "plan": "starter",
  "upgradePlan": "pro",
  "limitKey": "contacts",
  "current": 500,
  "max": 500
}

Lead capture API

Submit a lead from your website

The one endpoint designed to be called from outside the application.

Post your website form submissions here to create leads directly in Contacts. Authorize the request with the form secret from the Integrations page. The endpoint accepts cross-origin requests, so it can be called from the browser as well as from your server.

POST/api/contacts

Create a lead from a website form submission.

Auth: Form secret in the x-contact-secret header

Body

name*stringThe lead's full name.
email*stringA valid email address. Used to recognise repeat submissions.
phone*stringDigits only, at least 10.
companystringCompany name.
projectSlugstringRoutes the lead to a project and its assignees.
leadScorenumber0 to 100.
statusstringOne of your organization's contact statuses.
stagestringNot Contacted, No Response, Follow Up or Connected.
sourcestringWhere the lead came from, such as Website Form.
commentstringFree-text note from the form.
utm_sourcestringCampaign source.
utm_mediumstringCampaign medium.
utm_campaignstringCampaign name.
utm_termstringCampaign term.
utm_contentstringCampaign content variant.
page_titlestringTitle of the page the form was on.
form_titlestringName of the form that was submitted.
page_urlstringURL the form was submitted from.
customFieldsobjectValues for any custom contact fields, keyed by field id.

Returns. The created contact. If the email or phone matches an existing lead, the submission is recorded against that contact as an enquiry instead of creating a duplicate.

  • Only name, email and phone are required — everything else is optional.
  • Repeat submissions from the same lead are rate limited; exceeding the limit returns 429.
  • Team members are notified when a lead arrives.
OPTIONS/api/contacts

Cross-origin preflight for the lead capture endpoint.

Auth: None
Minimal submission
curl -X POST https://your-domain.com/api/contacts \
  -H "Content-Type: application/json" \
  -H "x-contact-secret: your_contact_secret" \
  -d '{
    "name": "Jane Smith",
    "email": "jane@example.com",
    "phone": "9876543210"
  }'
Full submission with campaign details and routing
curl -X POST https://your-domain.com/api/contacts \
  -H "Content-Type: application/json" \
  -H "x-contact-secret: your_contact_secret" \
  -d '{
    "projectSlug": "summer-lp-2026",
    "name": "John Doe",
    "email": "john.doe@example.com",
    "phone": "1234567890",
    "company": "Acme Inc",
    "leadScore": 75,
    "status": "warm",
    "source": "Website Form",
    "stage": "Follow Up",
    "comment": "Interested in a product demo",
    "utm_source": "google",
    "utm_medium": "cpc",
    "utm_campaign": "summer_sale",
    "page_title": "Contact Us - Acme Inc",
    "form_title": "Contact Form",
    "page_url": "https://example.com/contact"
  }'

Treat the secret like a password

Anyone holding it can write leads into your organization. Prefer sending it from your server or form handler, and rotate it from the Integrations page if it leaks.

Contacts API

Contacts

GET/api/contacts

Every contact in the organization.

Auth: SessionPermission: contacts:read

Returns. An array of contacts. Restricted lead visibility narrows this to the caller's assigned leads.

GET/api/contacts/paginated

One page of contacts, with search and filters applied.

Auth: SessionPermission: contacts:read

Query parameters

pagenumber1-based page number. Defaults to 1.
limitnumberRecords per page. Defaults to 10.
searchQuerystringMatches name, company, email or phone.
filtersjsonA JSON array of filter rows. Supported fields: status, source, stage, assignment, assignedTo, month, deals.

Returns. { contacts, totalPages, currentPage }

GET/api/contacts/recents/{limit}

The most recently created contacts.

Auth: SessionPermission: contacts:read

Returns. An array of contacts, newest first.

GET/api/contacts/{contactId}

A single contact.

Auth: SessionPermission: contacts:read

Returns. { contact }

PUT/api/contacts/{contactId}

Update a contact.

Auth: SessionPermission: contacts:write

Body

any contact fieldvariesSend only the fields you are changing.

Returns. The updated contact. The change is recorded on the contact's activity timeline.

DELETE/api/contacts/{contactId}

Delete a contact.

Auth: SessionPermission: contacts:delete
DELETE/api/contacts/bulk-delete

Delete several contacts at once.

Auth: SessionPermission: contacts:delete

Body

(body)*string[]An array of contact ids.

Returns. { deletedCount }

PUT/api/contacts

Bulk import contacts.

Auth: Session — administrators onlyPermission: contacts:write

Body

(body)*Contact[]An array of contacts, each validated the same way the form is.

Returns. { success, failed, errors, imported } so partially successful imports report exactly which rows were rejected and why.

GET/api/contacts/{contactId}/activity

The activity timeline for a contact.

Auth: SessionPermission: contacts:read

Returns. Entries describing what changed, who changed it and when — covering created, updated, deleted, assigned, unassigned and enquiry_added, for both the contact and its deals.

POST/api/contacts/{contactId}/assign

Assign a contact to a team member.

Auth: SessionPermission: team:write

Body

assignedTo*stringThe id of the member to assign the contact to.

Returns. The updated contact. The assignee is notified.

DELETE/api/contacts/{contactId}/assign

Remove the current assignment.

Auth: SessionPermission: team:write
GET/api/contacts/refresh-state

A lightweight signal the interface uses to tell whether the contact list has changed.

Auth: SessionPermission: contacts:read

Follow-ups

GET/api/contacts/{contactId}/followups

Follow-ups scheduled for a contact.

Auth: Session

Returns. An array of follow-ups with their due date, message and status.

POST/api/contacts/{contactId}/followups

Schedule a follow-up.

Auth: Session

Body

dueAt*stringWhen the reminder is due, as an ISO date.
message*stringThe reminder text.

Returns. The created follow-up, starting in the pending state.

PUT/api/contacts/{contactId}/followups/{followupId}

Update a follow-up, for example to reschedule it or mark it completed.

Auth: Session
DELETE/api/contacts/{contactId}/followups/{followupId}

Delete a follow-up.

Auth: Session
GET/api/followups/dashboard

Follow-ups for the dashboard.

Auth: SessionPermission: contacts:read

Returns. { upcoming, recentProcessed }

Deals API

Deals

GET/api/deals

Every deal in the organization.

Auth: SessionPermission: deals:read
POST/api/deals

Create a deal.

Auth: SessionPermission: deals:write

Body

title*stringName of the deal.
value*numberDeal value, zero or above.
stage*stringOne of your organization's pipeline stages.
probability*number0 to 100.
openDate*stringWhen the deal opened.
contact*stringThe id of the contact this deal belongs to.
descriptionstringLonger description.
commentstringFree-text note.
closeDatestringWhen the deal closed or is expected to.
customFieldsobjectValues for any custom deal fields.

Returns. The created deal.

GET/api/deals/paginated

One page of deals, with search and filters applied.

Auth: SessionPermission: deals:read

Query parameters

pagenumber1-based page number. Defaults to 1.
limitnumberRecords per page. Defaults to 10.
searchQuerystringMatches the deal title.
filtersjsonA JSON array of filter rows. Supported fields: stage, month.

Returns. { deals, totalPages, currentPage } with each deal's contact included.

GET/api/deals/{dealId}

A single deal with its contact.

Auth: SessionPermission: deals:read

Returns. { deal }

PUT/api/deals/{dealId}

Update a deal.

Auth: SessionPermission: deals:write

Returns. The updated deal. Moving a deal into a won stage can trigger the external database sync if it is configured.

DELETE/api/deals/{dealId}

Delete a deal.

Auth: SessionPermission: deals:delete
GET/api/deals/refresh-state

A lightweight signal the interface uses to tell whether the deal list has changed.

Auth: SessionPermission: deals:read

Workspace API

Projects

GET/api/projects

All projects with their assignees.

Auth: SessionPermission: contacts:read

Returns. { projects }

POST/api/projects

Create a project.

Auth: Session

Body

name*stringDisplay name, up to 120 characters.
slug*stringLowercase letters, numbers and hyphens, for example summer-lp-2026. This is the value your website form sends.
assigneeUserIdsstring[]Members who receive leads from this project.
statusstringactive or archived. Defaults to active.

Returns. { project }

GET/api/projects/{projectId}

A single project.

Auth: Session
PATCH/api/projects/{projectId}

Update a project — rename it, change assignees, or archive it.

Auth: Session
DELETE/api/projects/{projectId}

Delete a project.

Auth: Session

Team

GET/api/team/members

Members of the organization with their roles.

Auth: SessionPermission: team:read
GET/api/team/organization

Details about the current organization.

Auth: SessionPermission: team:read
GET/api/team/assignments

Which leads are assigned to whom.

Auth: SessionPermission: team:read

Query parameters

filtersjsonA JSON array of filter rows to narrow the list.

Returns. { assignments }

POST/api/team/invite

Invite someone to the organization.

Auth: SessionPermission: team:write

Body

email*stringAddress to invite.
rolestringadmin or member.
  • Returns a seat limit error if the plan has no seats left.

Notifications

GET/api/notifications

Your notifications.

Auth: Session

Query parameters

unreadOnlybooleanPass true to return only unread notifications.
limitnumberHow many to return. Defaults to 50.

Returns. Notifications newest first, plus the unread count.

POST/api/notifications

Mark notifications as read in bulk.

Auth: Session
PATCH/api/notifications/{notificationId}

Mark one notification as read.

Auth: Session
DELETE/api/notifications/{notificationId}

Delete a notification.

Auth: Session

Resources

GET/api/resources

Files previously emailed to contacts.

Auth: SessionPermission: contacts:read

Query parameters

pagenumber1-based page number.
limitnumberRecords per page.
searchQuerystringMatches the file name or the recipient.
filtersjsonA JSON array of filter rows.

Returns. A page of resources with file name, size, recipient, subject and when it was last sent.

GET/api/resources/{resourceId}

A single resource and its details.

Auth: SessionPermission: contacts:read

Reporting API

Reports and revenue

GET/api/reports/data

The dataset behind the Reports page.

Auth: SessionPermission: reports:read

Query parameters

monthFilterstringcurrent-month, last-month, last-3-months or last-6-months.
filtersjsonA JSON array of filter rows.

Returns. { contacts, deals, aiCalls } for the selected period, ready to chart.

GET/api/revenue

Revenue summary.

Auth: SessionPermission: revenue:view

Query parameters

targetnumberA revenue target to compare achievement against.
GET/api/currency/rates

Exchange rates used to display values in your chosen currency.

Auth: Session

Admin analytics

These endpoints back the Admin dashboard and are available to administrators only.

GET/api/admin/stats

Organization totals.

Auth: Session — administrators only

Returns. { totalContacts, totalDeals, totalCallRecordings }

GET/api/admin/trends

Trends over time and current distributions.

Auth: Session — administrators only

Returns. { trends, dealStages, contactStatuses }

GET/api/admin/member-behaviors

Per-member activity — contacts created, deals created and calls made.

Auth: Session — administrators only
GET/api/admin/activity-stream

A live feed of recent activity across the organization.

Auth: Session — administrators only

Configuration API

Organization settings

GET/api/org-config

The organization's configuration — terminology, stages, statuses, custom fields, currency, visibility, integrations and feature toggles.

Auth: SessionPermission: settings:read
  • Stored credentials are never returned. Integration passwords and webhook header values come back as __saved__.
  • Send __saved__ back on save to keep the stored credential, or a new value to replace it.
PUT/api/org-config

Update configuration.

Auth: SessionPermission: settings:write

Body

(partial config)objectSend only the sections you are changing.
POST/api/org-config

Reset configuration back to defaults.

Auth: SessionPermission: settings:write
GET/api/settings/contact-secret

The secret your website form uses to submit leads.

Auth: Session

Integrations

GET/api/integrations/status

Connection status and usage for every integration.

Auth: SessionPermission: settings:read
GET/api/email/google/status

Whether Gmail is connected, and for which account.

Auth: Session
GET/api/email/google/auth

Begins connecting a Google account. Redirects to Google.

Auth: Session
GET/api/email/google/callback

Where Google returns after you grant access. Not called directly.

Auth: Session
GET/api/settings/twilio

The current Twilio voice configuration.

Auth: SessionPermission: settings:read
POST/api/settings/twilio

Save the Twilio voice configuration.

Auth: SessionPermission: settings:write
DELETE/api/settings/twilio

Disconnect Twilio.

Auth: SessionPermission: settings:write
POST/api/integrations/twilio/test

Check the Twilio configuration before relying on it.

Auth: SessionPermission: settings:write
POST/api/integrations/custom-sql/test

Check the external database connection and column mapping.

Auth: SessionPermission: settings:write
POST/api/integrations/webhook/test

Send a test delivery to one configured API call.

Auth: SessionPermission: settings:write

Body

idstringThe configured call to test. Omit to test an unsaved draft.
namestringDisplay name.
url*stringThe https endpoint to POST to.
headers{key,value}[]Headers to send. A value of __saved__ means keep the stored one.
bodyTemplate*stringJSON body with {{deal.title}} style placeholders.

Returns. { success, status, attempts, responseBody } — the receiver's status code and a truncated response body.

  • Sends sample values, never a real customer record.
  • Returns 400 with the failure reason when the endpoint rejects the delivery.

Email and calls

POST/api/emailing

Send an email to a contact.

Auth: SessionPermission: email:send

Body

to*stringRecipient address.
subject*stringSubject line.
body*stringMessage body.
attachmentsfile[]Files to attach. Send the request as multipart/form-data to include them.
  • Accepts JSON, or multipart/form-data when attaching files.
  • Attachments are kept in Resources so they can be re-sent later.
  • Counts towards your plan's monthly email allowance.
POST/api/calls/initiate

Start a call to a contact.

Auth: SessionPermission: calls:initiate

Body

contactId*stringThe contact to call.
userPhoneNumberstringThe number to connect the call to.
notesstringNotes to store against the call.
GET/api/calls/{callSid}/status

The current status of a call.

Auth: SessionPermission: calls:view
POST/api/twilio/token

A short-lived token that lets the browser place calls.

Auth: SessionPermission: calls:initiate

Provider callbacks

Several endpoints exist purely so the telephony provider can report call, dial and recording status back to the application. They are called by the provider, not by you, and are not part of the public surface.

Plan and billing

GET/api/plan/status

The organization's current plan and trial state.

Auth: Session

Returns. { planSlug, planLabel, locked, trialDays, daysRemaining, orgCreatedAt }

GET/api/billing/plans

The plans available to subscribe to, with their features.

Auth: Session
POST/api/plan/sync-seats

Re-synchronise the organization's seat allowance with its subscription.

Auth: Session

Real-time updates

The application keeps open pages current by subscribing to a server-sent event stream. When something changes, the stream names the affected area and the interface refetches just that data.

GET/api/realtime

A server-sent event stream of change notifications.

Auth: SessionPermission: contacts:read, deals:read or settings:read depending on what you subscribe to

Returns. text/event-stream. An open event on connect, then invalidate events naming the entity that changed.

EntityChanges when
contactsA contact is created, updated, assigned or deleted
dealsA deal is created, updated or deleted
notificationsYou receive a new notification
orgConfigAn administrator changes organization settings
integrationsAn integration is connected, changed or disconnected
Events on the stream
{ "type": "open" }
{ "type": "invalidate", "entity": "contacts" }
Back to homeSalesFlow by Modifyed Digital