Pricing

Directory and CRM

The directory family is the workspace's canonical registry of external parties — the people and organisations every other desk resolves its counterparties through. The crm family is the revenue desk built on top of it: deals, accounts, playbooks, and escalations. Scopes: directory.read / directory.write and crm.read / crm.write.

Awareness scoping — the Directory's core rule

Directory reads are awareness-scoped at the query layer. A record marked named-only is absent from every result for a seat without a grant — not redacted, not hinted at, not countable. Two agents can run the same directory.search and correctly receive different result sets. Design for it: an empty result means "nothing you are allowed to know about", never "nothing exists".

Query the Directory

curl -X POST https://os.cohortapp.com/api/v1/directory.search \
  -H "Authorization: Bearer $COHORT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"params": {"q": "acme", "limit": 10}}'

Reads: search, listPeople, listOrgs, getPerson, getOrg, listLists, listCaptures, listMerges, listAwarenessRequests, plus ask (a grounded question over the Directory) and exportVcard — both audited side-effecting reads.

Writes: createPerson / updatePerson, createOrg / updateOrg, contact channels (addChannel, removeChannel, setPrimaryChannel), links (linkParty, unlinkParty), lists (createList, addToList, removeFromList, shareList), and captures (proposeCapture, resolveCapture) — the intake lane that turns an observed counterparty into a record.

Structural verbs are human-only

executeMerge, revertMerge, setAwareness, archivePerson, and archiveOrg refuse an agent actor in the domain layer — the call creates a review item for a human instead of mutating. Agents propose (proposeMerge, requestAwareness); humans dispose. Expect a result that says a review was filed, not a completed mutation.

Run the revenue desk

The crm family (44 methods) mirrors the app's deal surfaces exactly — including its holds.

TaskMethods
Deal lifecyclecreateDeal, updateDeal, moveStage, closeDeal, deleteDeal
Terms and playbooksproposeTerms, updateHeldTerms, holdNextStep, runNextBestAction, savePlaybook, togglePlaybook, deletePlaybook, compilePlaybook (a pure compile preview — persists nothing)
Sharing and delegationshareDeal, revokeDealShare, mintGuestToken, addCallGuest, delegate
Accounts and contactscreateAccount, updateAccount, archiveAccount, createContact, updateContact, deleteContact, linkContact
Record keepinglogInteraction, linkEmail, linkFiles, pinNote, redactInteraction, logDealDecision, taskFollowThrough
Escalations and targetssignEscalation, returnEscalation, setTarget
ReadslistDeals, getDeal, listEscalations, listAccounts, listContacts, listInteractions, listPlaybooks, getTargets, ask

Playbook holds return as results

crm.proposeTerms is the enforcement path for concessions. When proposed terms cross a playbook line — too deep a discount, a non-standard term — the call succeeds: the deal is placed on hold, the interaction log records it, and the result carries the hold:

{
  "ok": true,
  "result": {
    "dealId": "deal_…",
    "held": true,
    "playbookSlug": "discount-floor",
    "reason": "Discount beyond 20% needs a signature.",
    "marginImpactCents": -420000,
    "ledgerId": "ab12cd34"
  }
}

Report it exactly as it is — "held for signature — ledger #ab12cd34" — and never as a completed concession. A human releases the hold from the deal surface (or an agent updates the held terms with updateHeldTerms to bring them inside the line).

Two verbs are human-signature acts in the domain layer regardless of scope: signEscalation / returnEscalation (deciding an escalated deal) and setTarget's targetCents (setting a revenue target). An agent-plane call to these refuses — the same rule the app enforces.

Contact cards vs. the Directory

The older contact family (contact.add / update / delete / list) manages contact cards on org content, and contacts.upsert feeds the knowledge-plane contact registry. For external people and companies, the Directory is the canonical registry — prefer it; the other two remain for their in-app surfaces.