- An active exact-address
alloworblockchoice takes precedence in either mode. - Without an exact choice, email uses matching
allowdomains in whitelist mode orblockdomains in blacklist mode. - Unmatched addresses are denied in whitelist mode and allowed in blacklist mode.
Contact visibility
Email and phone visibility is all-or-nothing for each contact and identity. A visible group exposes all of that contact’s identifiers of that kind, including in search, lookup, vCard export, and contact context. Permission to communicate remains independent for each address. A fully hidden contact returns404 by ID and is absent from listings.
Choose group visibility separately from each address’s communication permission:
Without an explicit group-visibility choice, any communication-permitted address makes that group visible. Existing mixed communication choices stay mixed, but the agent can see every address in that group. Seeing an address does not authorize sending to it.
Profile is the parent permission for the contact. When Profile is hidden, Email, Phone, and Memories are also hidden, and no saved address is contactable through this contact. When Profile is visible, you can independently hide Memories or make Email and Phone view-only. Existing authorized conversation history is not erased.
Hosted voice in YOLO mode can read all contacts, fields, and memories in its organization regardless of these settings. Ordinary identity-scoped API, SDK, CLI, MCP, and webhook access still follows the contact policy. Setting an identity’s default voice mode to YOLO does not change those ordinary reads.
Read and update contact access
visible covers the whole email or phone group. contactable lists only the current addresses the agent may contact. In this example, the agent can see all phone numbers but cannot contact them.
- PATCH preserves omitted fields. An empty PATCH or an empty group object changes nothing on its own.
- A supplied
contactablelist replaces communication choices for that group’s current addresses. Listed addresses become explicit allows; all other current addresses become explicit blocks. An empty list blocks all current addresses. - A nonempty
contactablelist makes its group visible whenvisibleis omitted. An empty list preserves the previous visibility whenvisibleis omitted. visible: falsehides the group and blocks all of its current addresses. Addresses subsequently added to an explicitly hidden group are also blocked.- An explicit standalone exact-address allow can reveal a uniquely matched saved contact’s group while Profile is enabled, without allowing its other addresses.
profile: falsehides Email, Phone, and Memories and clears the contactable lists. A request that enables any child permission while the resulting Profile permission is false returns422.- Choices persist when the identity’s whitelist/blacklist mode changes. No revision or previous-action field is required; concurrent edits to different fields preserve each other.
contactable list accepts at most 50 unique normalized addresses. Phone values must be E.164. Nulls, unknown fields, duplicate normalized addresses, and visible: false with a nonempty contactable list return 422. An address outside the contact returns 400; an unavailable agent/contact returns 404; insufficient authority returns 403.
Use SDK/CLI 0.6.12 or later with admin credentials for local validation of Profile-child contradictions:
{"email":{"visible":true,"contactable":[]}}. The existing contacts.access.list SDK method and contacts access list CLI command return read-only compatibility metadata, not these selected-agent access settings.
Read and update yes/no permissions
Use SDK/CLI
0.6.12 or later for local validation of Profile-child contradictions:
{"emails":{"ada@example.com":true},"profile":true,"memories":false}. To save initial choices with a new contact, use create contact with permissions.
Advanced policies
Use this interface when you need inherited visibility settings or guarded exact-address edits:contact_id, revision, identity_id, addresses, effective_visibility, and visibility. Each address has kind, value, nullable label, stored action, and effective allowed. Without the optional identity_id query, addresses is empty and identity_id and effective_visibility are null.
Read the current policy, then supply its revision and each edited address’s observed action:
allow and block set explicit exact-address choices. inherit removes that exact choice so domain rules and the channel mode determine communication access. There are no contact-wide Email or Phone communication defaults.
The optional visibility object contains defaults: {profile, memories} and identities: [{identity_id, profile, memories}]. Decisions are allow, block, or inherit. An identity override inherits its contact default. When both Profile decisions inherit, Profile is enabled. A blocked effective Profile requires blocked Memories and prevents Email or Phone address allows for the selected identity.
Omitting visibility preserves all Profile/Memories settings. Supplying it replaces that entire portion, so retain other identities’ settings. visibility: null, unknown fields, duplicate normalized addresses, and invalid decisions return 422. Up to 500 address edits and 500 distinct identities are accepted. Stale revisions or changed observed actions return 409 without saving changes.
Replacing Profile/Memories settings preserves email/phone visibility while Profile stays enabled. Blocking Profile makes those visibility settings ineffective and prevents an exact-address allow from revealing contact data.
Python uses communication_policy.get(contact_id, identity_id) and .replace(..., expected_revision=..., identity_id=..., addresses=[ContactAddressUpdate(...)]). TypeScript uses communicationPolicy.get(contactId, identityId) and .replace(contactId, {expectedRevision, identityId, addresses}), with expectedAction on address edits. Rust uses communication_policy().get_for_identity(contact_id, identity_id) and replace with ReplaceContactCommunicationPolicy; replace_with_visibility also replaces visibility.
The CLI provides contacts communication-policy get CONTACT_ID --identity-id IDENTITY_ID and set CONTACT_ID --file policy.json. Its file uses the TypeScript names expectedRevision, identityId, and expectedAction, including identityId within optional visibility overrides.
Preview an identity’s saved view
contact: null when that view cannot see the contact. Otherwise contact includes the permitted fields, memory_count, and latest_memory. Denied memories produce zero and null without revealing their existence.
visibility.profile and visibility.memories report access even when a group has no stored content. Memories is always false when Profile is false. Existing email and phone indicators mean their visible identifier arrays are nonempty. full_profile remains a conservative legacy aggregate; use the individual visibility fields for new interfaces. The identity listing returns items, limit, offset, and has_more; an agent can list only its own view.
Use inkbox.contacts.communication_policy.preview(contact_id, identity_id) in Python or inkbox.contacts.communicationPolicy.preview(contactId, identityId) in TypeScript. The CLI provides contacts communication-policy preview CONTACT_ID IDENTITY_ID and contacts communication-policy list HANDLE.
Manage an identity’s contact permissions
The response contains
items, limit, offset, and has_more. Each item has:
Effective communication access includes standalone address, domain, and number
rules.
no_identifiers means no identifiers are stored, not that access is
denied. Resetting a policy to inherited values does not reset its revision.
Other identities’ overrides are not included in this roster. Boolean permission updates preserve their settings automatically.
Phone compatibility
Existing phone and iMessage rule methods remain supported.phone_filter_mode and imessage_filter_mode are aliases: setting either changes both. Supplying conflicting values in one request returns 422.
Identity-level permission configuration does not require a dedicated phone number. Older SDK helpers may still check for one locally; use their existing iMessage methods or upgrade. Releasing or replacing a phone number preserves the identity’s permissions, and enabling another transport does not reset them.
Contact edits
Changing the identifiers of an existing contact requires admin credentials or the Inkbox Console. Added identifiers follow their exact-address rules, email domain rules, and channel mode, except that an explicitly hidden group keeps added identifiers blocked. Humans and admin API keys can remove identifiers or delete a contact without resetting Profile or Memories settings. Exact-address rules survive contact or identifier deletion. Agent profile edits cannot grant communication permissions. Agent profile PATCH requests must omitemails and phones, even when their values are unchanged. Agent credentials cannot delete contacts with configured Profile or Memories restrictions; use an admin API key or the Inkbox Console. Merging contacts with different permission settings returns 409 with detail.error: "contact_policy_mismatch" and a readable detail.message.
MCP users manage communication rules in the authenticated Inkbox Console. The agent can inspect its permitted contact view but cannot change its own rules.
Webhook replays refresh contact names and memories against current permissions. A visible name can accompany an empty memory list, but memories are never included without Profile access. Archived contact-scoped conversation context is omitted when it cannot be refreshed; the original event and directly scoped conversation history remain available.
