This page describes the contract heyBTW is standardizing across its MCP tools.
It separates the behavior available today from the versioned target so clients
do not mistake planned fields for live fields.
Current compatibility boundary
The current Python MCP surface uses the response shapes documented on each tool
reference page. When a versioned replacement is published, existing fields
remain supported through the end of its published deprecation window.
This page’s opaque identity, privacy-projection, and deletion behavior is a
proposed versioned target, not current production behavior. Stable opaque
company_id, contact_id, and event_id fields are not present
consistently on the current Python surface. Do not fabricate them from
names, email addresses, or provider IDs.
Stable entity references
The versioned identity contract uses typed references:
IDs are:
- stable across tools and sessions inside one authorized workspace;
- opaque and free of email, domain, CRM, and provider identifiers;
- intentionally different for the same underlying entity in another
workspace;
- resolved only after workspace authorization;
- revoked from public responses when the entity is deleted.
The _v1_ token in an ID is the handle-format version, not the MCP response
contract version. MCP contract v2 can carry a v1-format handle. A response
version change does not silently rotate entity IDs. Handle format v1 uses
exactly 22 unpadded base64url characters after the entity prefix.
Email, domain, CRM IDs, and event-platform IDs are lookup keys or provenance.
They are not canonical public identity. All display attributes are optional,
including company domains and names, contact emails and names, and event names
and slugs. They appear only when the caller, entity, and tool purpose are
authorized by heyBTW’s field-disclosure policy. Event slugs include a random
workspace-specific suffix and are not cross-workspace join keys.
Company matching uses a normalized registrable domain, rejects personal-email
providers, and excludes the workspace’s own domain. A workspace alias applies
only after heyBTW verifies the required authority for both the alias and its
canonical target. Verifying one endpoint cannot bind it to an arbitrary
company. A personal-email contact has no company reference.
Contact email matching trims surrounding whitespace and lowercases only the
domain. The local part, including case and plus-addressing, remains distinct
unless a verified provider-specific namespace rule proves two forms equivalent.
Person@example.com, person@example.com, and
person+event@example.com are not automatically merged.
A job change preserves a contact ID only when verified continuity evidence
supports the same person; otherwise the new email creates a separate contact and
handle. A rebrand preserves company continuity only through verified two-sided
alias authority or an audited merge. Similar names never establish identity by
themselves.
Privacy and deletion
Workspace query scoping is live today. Foreign opaque-handle behavior and
the HEY-818 deletion guarantees below are proposed targets and are not live.
The global data-subject deletion endpoint remains unavailable until Legal
and Security approve its authentication, evidence, notification, exception,
appeal, and reversal runbook.
Every read is workspace-scoped at the data-access boundary. A handle from
another workspace is treated exactly like an unknown handle.
When an authorized workspace deletes a contact, heyBTW immediately denies reads,
fences in-flight writers, then removes that workspace’s public handle, PII
projection, CRM and provider mappings in scope. Imports, syncs, enrichment,
webhooks, and retries cannot recreate the contact. A verified global
data-subject request revokes all public handles and aliases in scope.
Deleted contacts are excluded from MCP tools, heyBTW AI, exports, lists, search,
and relationship endpoints. Person-level graph edges are removed. No aggregate
derived from those edges remains unless a separately approved privacy contract
defines and tests its re-identification protections.
Versioning and the existing cmp_ ID
The in-app TypeScript implementation of get_partner_overlaps currently emits
a deterministic cmp_ company value. It is not available through the public
mcp.heybtw.com Python gateway. That value is a v1 compatibility key, not the
final opaque identity scheme, and will not be silently redefined in place.
Because it is derived from the company domain, it is a temporary
cross-workspace-correlation exception and does not satisfy the opaque-ID privacy
guarantee. Do not adopt it in a new integration or treat it as durable identity.
A new major response version will introduce the opaque identity references.
HEY-393 owns the negotiation mechanism, supported values, default behavior, and
discovery contract. Until that mechanism is published on the affected tool
reference pages, the current response remains the default and clients cannot
request the target version. After publication, selector-free requests continue
to receive the current contract through the entire deprecation window. Clients
selecting a supported new version use the documented mechanism and migrate
before that window expires. The default cannot change silently; any
post-deprecation fallback must be published before the window begins. This page
does not invent a header, parameter, or tool-name convention. Response-version
negotiation and handle-format versioning are separate compatibility axes.
Identity lookup and handle allocation require a trusted server-derived
authorization context that binds workspace membership, partner and sponsor
visibility, and the allowed entity set. They also require a closed tool-purpose
value. Request parameters cannot create or widen either value, and unauthorized
entities fail closed before lookup or handle allocation.
Response rules
Versioned responses converge on:
- an explicit status;
- typed data;
- metadata with workspace, tool version, generation time, freshness,
Context Graph coordinates, pagination, and rate-limit state;
- structured errors that state what failed, what to check, and what to do;
- cursor pagination without silent truncation;
- source-backed facts instead of unverifiable scores.
Consumer rules for the versioned target
The per-tool reference pages remain authoritative for current production
behavior. Until a tool advertises the versioned response contract, do not assume
that pagination, coverage, or structured recovery metadata is present.
- Treat IDs as opaque. Do not parse or recreate them.
- Scope cached IDs by workspace, entity type, and handle-format version.
- When present, use
company_domain only as an external CRM lookup input, not
as a replacement for company_id or as a cross-tool identity.
- Do not use email as a durable person ID.
- Check pagination and coverage metadata before claiming that a result is
complete or zero.
- Read structured error recovery fields before retrying.
- Never persist provider IDs as cross-platform identity.
See MCP Tools for setup and the current tool catalog.