Contacts, companies and deals
Business Studio’s CRM is not a separate product. A contact, a company and a deal are three kinds of card on the same board as everything else — filed, tagged, searched and moved the way every other card is — with three things the other kinds do not have: they are shared with your whole organisation, a deal moves along a sales pipeline instead of the four-column board, and every one of them carries a timeline and linked records.
The design decision behind this (build on the board rather than adopt a standalone CRM) is
recorded in the repository under tasks/spike-crm-build-vs-adopt.md.
Shared with the organisation
Section titled “Shared with the organisation”Most cards are private to whoever created them. A contact, a company or a deal is visible to every member of the organisation: a colleague sees the person you filed, can log a call on them, and can link them to a deal of their own. Their plain tasks stay theirs, and yours stay yours — a colleague’s private card reads as “Card not found”, exactly like a missing one.
Identity is shared too. A person is keyed on their LinkedIn profile, then their email, then
their phone; a company on its domain (read from the website you give) or its LinkedIn page. Two
people in the organisation filing the same person or company land on one card, whichever of
them got there first. An email is keyed on the mailbox it reaches: jane+news@acme.com is
jane@acme.com on any domain, and at Gmail jane.doe@gmail.com is janedoe@gmail.com too.
Dots count everywhere else, where j.doe and jdoe may be two people. The card keeps the address
as it was written.
The three kinds
Section titled “The three kinds”| Kind | Title is | Structured fields | Enters at |
|---|---|---|---|
| Contact | the person’s name | first/last name, email, phone, company (a label), role, LinkedIn profile, location, summary | captured, already handed to NEO, whose contact squad looks them up on LinkedIn, fills the empty fields and writes what it found to the timeline |
| Company | the organisation’s name | domain, website, industry, size, location, LinkedIn company page, summary | captured (no lookup yet) |
| Deal | the opportunity | amount, currency, expected close date, company (a label) | new on the pipeline |
A contact’s company text is a display label. The real relation — which company card a contact
or a deal belongs to — is a link (below), so a company page can list its people and its
deals, and a contact can move employer without editing anyone’s deal.
Create them from Sales & CRM in the sidebar (Contacts, Companies, Deals), from the + Create
button, by converting a plain task on its card (a task that turns out to be a person, a company or
an opportunity), or from the API and the Claude connector.
The sales pipeline
Section titled “The sales pipeline”Open Deals and the board draws the pipeline as columns: New → Qualified → Proposal → Won,
with Lost behind the Archived toggle. Drag a deal between columns, or pick the stage on its
card; the stage is validated (a value the pipeline does not know is refused with the real
options) and the card’s board column follows it — won files under Done, lost under Archived.
Every stage move is written to the deal’s timeline as a stage change, with who moved it and
from where.
Each column header shows the total amount of the deals in it when they share one currency.
?columns=spine on the board URL shows deals on the ordinary four-column board instead.
Timeline
Section titled “Timeline”Every contact, company and deal has a timeline beneath its card: notes, calls, meetings and emails you log; stage changes; and the result of each LinkedIn lookup, with what was found, which fields it filled, and its confidence. To look someone up again, take the card back from NEO and hand it over again. Entries are append-only — an audit trail that can be edited is not one — and the newest is first.
Suggest next step asks the assistant for the one most useful next action on this record, grounded in the card and its last ten timeline entries. The answer lands on the timeline as a system entry a few seconds later. It needs a connected AI channel; without one the button says so instead of pretending.
Linked records
Section titled “Linked records”Three typed relations, all from the card’s Linked records section:
- Company of — a contact or a deal belongs to a company.
- Contact on this deal — a person is party to a deal.
- Contact of — any card is about a person (a support thread, a task).
Both directions show on both cards, and a link that does not make sense (a company as a deal’s contact, say) is refused before it is written. On a deal, Contact on this deal and Contact of both count as the deal’s contacts.
Invoicing a deal
Section titled “Invoicing a deal”Create invoice on a deal drafts its invoice and opens it — the month’s activity report for a mission (a won deal with a daily rate; pick this month or last beside the button), the deal’s amount otherwise, or the draft it already has. An invoice can only be raised from a deal, and only once that deal is linked to exactly one company and at least one contact — the button says which is missing. The deal’s timeline then follows the money: an “Invoice … drafted” line when it is created, and an “Invoice … paid” line, once, when Stripe reports the payment.
What a client paid, bought and said
Section titled “What a client paid, bought and said”A contact or company card shows, under its fields, what the rest of the platform knows about that
person or organisation — over the last 90 days or the last year (?profileDays=90 keeps
the choice in the link):
- Invoices — number, status, paid date and amount, with the paid total per currency.
- Products & subscriptions — the lines of every non-void invoice, and the recurring schedules the client holds.
- Tickets — event ticket orders.
- X comments — replies and mentions filed in your Inbox whose author is the contact’s X
handle (the field accepts
@jdoe,jdoeor an x.com URL and storesjdoe).
A company’s view is its own plus every contact linked to it. On a post card, the same section lists who commented on X and whether each one is already a contact.
How a billing customer finds its card: when a customer or a ticket order is created, its email is matched (case-insensitively) against the org’s contact cards, and the company comes from that contact’s company link, or from a company card whose domain is the email’s own (never a gmail-type address). Nothing is created for an email that matches no card — and a card filed after the customer was billed still sees its history, matched by email.
Your own cards and private facts
Section titled “Your own cards and private facts”My card and My company in the account menu (/me, /me?card=company) open your own contact
and company cards. They are created on first visit and are private: unlike every other contact or
company, a colleague cannot see them, find them or edit them.
Some facts do not belong on a card everyone in the org reads — an IBAN, a VAT or registration number, a legal name, a registered or home address, a date of birth, a personal phone. The Facts section of a contact or company card holds them: what you add there is visible to you only unless you tick Share with my organisation, even on a shared card. An IBAN must pass its checksum. Only a person adds these — enrichment never looks them up. Remove one with its ✕; it is kept in the card’s history rather than deleted.
Who is who to whom
Section titled “Who is who to whom”Beyond Works at (a contact’s company), a contact or company card can record who it is to another company — under Linked records on its Properties tab:
| Relationship | From | To |
|---|---|---|
| Shareholder of | a contact or a company | a company |
| Adviser of | a contact | a company |
| Member of | a contact or a company | a company (an association, a board, a network) |
| Partner of | a company | a company |
The other end reads the other way round — Acme’s card lists its Shareholders. Two relations are never typed: the mailing audiences a person is on and the events they took part in come from audience membership and ticket orders, and appear in the card’s Across the platform section.
Messages sent
Section titled “Messages sent”Messages sent in a contact’s or company’s Across the platform section lists what the platform
sent that person: every email campaign they received (with the subject they saw — {{name}}
filled in), the purchase receipt for an offer they bought, and each subscription invoice
email. One row per recipient per send, logged once even if a send is retried. A person who gets a
contact card after a campaign went out still sees it — messages are matched by email address.
Emails you send from your own mailbox are not counted here.
Documents
Section titled “Documents”The Documents section of a contact, company, deal, task or user story holds links to where a
document lives — a Google Drive file, a Notion page, any web page. Nothing is copied: the card keeps
the title and the link. Attaching a link does not create a card; make a Doc card instead only when
the file needs its own owner, due date or place on the board. Paste a link, or pick a file from your connected Drive folder (type a folder path such as
clients/acme) or a page from your connected Notion database. Like a private fact, a document is
visible to you only unless you tick Share with my organisation; only the person who attached it
can remove it. A task or user story is yours alone, so its documents are too — there is no share option
there. ID papers, contracts and medical documents belong here, as links — never as facts.
Any link can be promoted with Make its own card on its row: it files a Doc card for that link,
grouped under the card you are on (Part of; it lists under Sub-cards in Properties). The link stays
where it is, and promoting the same link again opens the Doc card already there rather than making a
second. A Doc card is visible to your organisation, so a link only you can see — a private one, or any
link on a task or user story — asks first. Over the API this is
POST /api/tasks/:id/documents/:documentId/card, with { "share": true } to confirm that case.
Review
Section titled “Review”Review is the one place to clear what the knowledge layer is unsure about. It is computed live each time you open it, and nothing in it is applied or created until you click:
- Conflicts — a card field where two claims of similar weight disagree (a held claim). You see the card’s current value and every held value side by side; accepting one supersedes the others.
- Suggestions — a field with only proposed claims. Accept writes it onto the card, dismiss remembers the no.
- New people — email addresses you billed, sold a ticket to or sent a message to in the last year that have no contact card yet. Add to CRM files the contact; nothing is filed for you.
- Memories — something NEO, a squad, Claude (the
remembertool) or an import proposed for NEO to remember about you, such as “LinkedIn posts in French”. Keep applies it — for you, or, if you are an org admin, for the whole organisation — and NEO reads it on every card you hand it from then on. Dismiss means it is never proposed again. Kept memories, a memory you type yourself and the Import from Claude or ChatGPT box are on Memories (/memories).
Claims you cannot read (another member’s private facts) and cards you cannot see never appear, and stated-only fields such as an IBAN are never reviewed. When anything is open, Needs your attention carries one entry, Daily review: 2 conflicts · 3 suggestions · 1 new person · 1 memory to keep, that opens the page. There is no schedule and no email: the review is a page you visit.
Search
Section titled “Search”The board’s search box reaches the CRM fields, not only titles: type an email address, a phone number, a company name or a domain and the matching contact, deal or company comes up.
From the API
Section titled “From the API”All routes are session- or API-key-authenticated and org-scoped.
| Route | What it does |
|---|---|
POST /api/tasks/contacts | File a person; returns the existing card (200) when the identity is already known |
POST /api/tasks/companies | File an organisation; same idempotency, keyed on domain or LinkedIn page |
POST /api/tasks with destination: { scheme: "sales" } | File a deal; optional subStatus (a pipeline stage, validated) |
PATCH /api/tasks/:id with subStatus | Move a deal; the board status is derived from the stage |
PATCH /api/tasks/:id with payload: { contact | company | deal } | Set the structured fields |
GET / POST /api/tasks/:id/activities | Read or log the timeline (kind: note, call, meeting, email) |
GET / POST / DELETE /api/tasks/:id/links | Read, add or remove a typed link |
POST /api/tasks/:id/next-action | Ask for the next step; 202 with the run id, 409 with the remedy when no AI channel is connected |
POST /api/tasks/self | Your own private contact and company cards (created on first call) |
POST /api/tasks/:id/facts | State a fact (field, value, optional visibility: org|owner); a personal or banking field is private by default |
DELETE /api/tasks/:id/facts/:factId | Remove a fact you stated |
GET / POST / DELETE /api/tasks/:id/documents[/:docId] | Read, attach (url, title?, visibility?) or remove a document link |
GET /api/tasks/document-sources[/drive?path=|/notion] | Which sources you can pick from, and their files / pages |
GET /api/tasks/:id/profile?days=90|365 | A contact’s or company’s invoices, products, subscriptions, ticket orders and X comments; a post’s X commenters |
GET /api/tasks/review | The review: conflicts, suggestions (each a card, field, current value and its open claims, highest score first), newPeople, memories (your open memory proposals) and their counts |
GET /api/memories | What NEO remembers for you (applied: yours and the org’s) and what waits for you (proposed) |
POST /api/memories/import | { text, origin: "claude" | "chatgpt" | "other" } — a pasted memory export; each line becomes a proposal |
POST /api/memories/:id/accept · /dismiss · DELETE /api/memories/:id | Keep ({ scope: "personal" | "org" }), dismiss or forget — from a signed-in browser session only; an API key is refused |
GET /api/tasks/documents | Every document link you may read across the organisation, grouped by card |
GET /api/tasks/:id/activities?since=<ISO date> | The timeline from a date on (400 on an invalid date); still takes limit and beforeSeq |
GET /api/tasks?search=…&entity=contact | Search; every CRM row carries lastActivityAt |
The SDK mirrors them on platformClient.tasks: createDeal, updateDeal, createCompany,
listActivities, logActivity, listLinks, link, unlink, suggestNextAction, getProfile,
ensureSelfCards, stateFact, retractFact, listDocuments, attachDocument, detachDocument,
documentSources, browseDocumentSource, getReview, listAllDocuments.
From Claude
Section titled “From Claude”Through the Claude connector, Claude works the CRM the way you
do: create_task files a contact or a company, search_contacts finds a person by email, phone,
company or name, log_activity remembers a call or a meeting on a card, link_records puts a
contact at a company or on a deal, update_task moves a deal along the pipeline or sets its
amount, and get_task reads a CRM card with its timeline and links in one call — plus, for a contact or
company, a summary of the last year’s invoices, purchases, subscriptions and X comments, and for a
post, which of its X commenters are in your contacts.
From Gmail
Section titled “From Gmail”The Contacts from Gmail workflow template (/workflows → templates) files everyone who writes
to you as a contact card each morning: read_gmail → extract_contacts → tag. The
extract_contacts node reads each message’s From header — or its To, or both — and creates one
contact per address, titled with the sender’s display name, tagged from:gmail, keyed on the email
like every other capture, so a person who wrote twenty times is one card and a person a colleague
already filed is reused untouched. It skips your own account address, the addresses and domains you
list in Never capture, and automated senders (no-reply@, notifications@, …). It uses no AI:
the cards enter at captured, not handed to NEO. To look someone up, assign their card to NEO
and the contact squad fills in company, role and LinkedIn profile.
What is not here yet
Section titled “What is not here yet”- A lookup run for companies (the card’s lifecycle already reserves the state for it).
- Enriching every contact a Gmail extraction found in the same run:
update_contactwrites back one card, so the lookup is per card, through NEO. - Capturing a contact from a social comment — a commenter has no email or profile to key on.
- Calendar sync, custom fields and saved views.
- A daily digest proposing a contact card for a billing customer or ticket buyer no card matches.
- Declaring a Drive folder or Notion database the source of truth for a kind of record, and syncing from it.
- LinkedIn and Reddit comments: only X replies and mentions reach the Inbox.
- Payments as records of their own: a refund or a partial payment does not reach the deal; only an invoice turning paid does.
