{
  "schemaVersion": "1.0",
  "title": "Chatwoot contacts and companies",
  "description": "Use these 31 capabilities to find and maintain contacts, notes, companies, and their relationships. Treat every result as restricted customer data, including reads that need no human approval.",
  "canonical": "https://getaip.org/docs/connectors/chatwoot/capabilities/contacts-and-companies",
  "route": "/docs/connectors/chatwoot/capabilities/contacts-and-companies",
  "source": "docs/connectors/chatwoot/capabilities/contacts-and-companies.md",
  "protocol": "Agent Interoperability Protocol",
  "protocolVersion": "1.0",
  "section": "Connectors",
  "documentType": "Connector",
  "language": "en",
  "downloads": {
    "md": "/docs/download/connectors/chatwoot/capabilities/contacts-and-companies.md",
    "txt": "/docs/download/connectors/chatwoot/capabilities/contacts-and-companies.txt",
    "json": "/docs/download/connectors/chatwoot/capabilities/contacts-and-companies.json",
    "pdf": "/docs/download/connectors/chatwoot/capabilities/contacts-and-companies.pdf"
  },
  "content": {
    "format": "text/markdown",
    "markdown": "---\ntitle: Chatwoot contacts and companies\ndescription: >-\n  Use 31 exact customer-data capabilities with governed merge, import, export,\n  relationship, and deletion decisions\nkind: capability-reference\naudience: application-developer\nappliesTo: \"1.x\"\nwritingStandard: \"aip-docs/1.0\"\nlastReviewedRevision: \"97be86e9efedf07ecf1783b03800f683f107fb04\"\nconnector: chatwoot\ncapabilityIds:\n  - cap:chatwoot:contact.list\n  - cap:chatwoot:contact.create\n  - cap:chatwoot:contact.get\n  - cap:chatwoot:contact.update\n  - cap:chatwoot:contact.delete\n  - cap:chatwoot:contact.active\n  - cap:chatwoot:contact.search\n  - cap:chatwoot:contact.filter\n  - cap:chatwoot:contact.import\n  - cap:chatwoot:contact.export\n  - cap:chatwoot:contact.conversation.list\n  - cap:chatwoot:contact.inbox.create\n  - cap:chatwoot:contact.label.list\n  - cap:chatwoot:contact.label.update\n  - cap:chatwoot:contact.note.list\n  - cap:chatwoot:contact.note.create\n  - cap:chatwoot:contact.note.get\n  - cap:chatwoot:contact.note.update\n  - cap:chatwoot:contact.note.delete\n  - cap:chatwoot:company.list\n  - cap:chatwoot:company.create\n  - cap:chatwoot:company.get\n  - cap:chatwoot:company.update\n  - cap:chatwoot:company.delete\n  - cap:chatwoot:company.search\n  - cap:chatwoot:company.contact.list\n  - cap:chatwoot:company.contact.create\n  - cap:chatwoot:company.contact.delete\n  - cap:chatwoot:company.conversation.list\n  - cap:chatwoot:contact.merge\n  - cap:chatwoot:contact.contactable_inbox.list\naliases:\n  - Chatwoot customer-data capabilities\n  - Chatwoot contact and company operations\n---\n\n# Chatwoot contacts and companies\n\nUse these 31 capabilities to find and maintain contacts, notes, companies, and\ntheir relationships. Treat every result as restricted customer data, including\nreads that need no human approval.\n\nThe catalogue freezes capability IDs, provider methods, paths, and AIP policy\ncontracts. It does not freeze provider-specific contact or company body fields.\n\n## Family at a glance\n\n| Group | Operations | Reads | Mutations | High risk |\n|---|---:|---:|---:|---:|\n| Contact records and relationships | 16 | 7 | 9 | 3 |\n| Contact notes | 5 | 2 | 3 | 1 |\n| Companies and relationships | 10 | 5 | 5 | 2 |\n| **Total** | **31** | **14** | **17** | **6** |\n\nAll 31 capabilities are Tools. The method split is 14 `GET`, ten `POST`, three\n`PATCH`, and four `DELETE` operations.\n\nThe 14 reads are low risk. Eleven mutations are medium risk. The\n`contact.import` and `contact.export` POST operations plus the four deletes are\nhigh risk.\n\n## Contact record and relationship operations\n\n| Capability | Provider request | Purpose | Risk | Approval |\n|---|---|---|---|---|\n| `cap:chatwoot:contact.list` | `GET /api/v1/accounts/{account_id}/contacts` | List contacts | Low | No |\n| `cap:chatwoot:contact.create` | `POST /api/v1/accounts/{account_id}/contacts` | Create a contact | Medium | Required |\n| `cap:chatwoot:contact.get` | `GET /api/v1/accounts/{account_id}/contacts/{contact_id}` | Read one contact | Low | No |\n| `cap:chatwoot:contact.update` | `PATCH /api/v1/accounts/{account_id}/contacts/{contact_id}` | Update one contact | Medium | Required |\n| `cap:chatwoot:contact.delete` | `DELETE /api/v1/accounts/{account_id}/contacts/{contact_id}` | Delete one contact | High | Required |\n| `cap:chatwoot:contact.active` | `GET /api/v1/accounts/{account_id}/contacts/active` | List active contacts | Low | No |\n| `cap:chatwoot:contact.search` | `GET /api/v1/accounts/{account_id}/contacts/search` | Search contacts | Low | No |\n| `cap:chatwoot:contact.filter` | `POST /api/v1/accounts/{account_id}/contacts/filter` | Filter contacts | Medium | Required |\n| `cap:chatwoot:contact.import` | `POST /api/v1/accounts/{account_id}/contacts/import` | Import contacts | High | Required |\n| `cap:chatwoot:contact.export` | `POST /api/v1/accounts/{account_id}/contacts/export` | Export contacts | High | Required |\n| `cap:chatwoot:contact.conversation.list` | `GET /api/v1/accounts/{account_id}/contacts/{contact_id}/conversations` | List contact conversations | Low | No |\n| `cap:chatwoot:contact.inbox.create` | `POST /api/v1/accounts/{account_id}/contacts/{contact_id}/contact_inboxes` | Associate a contact with an inbox | Medium | Required |\n| `cap:chatwoot:contact.label.list` | `GET /api/v1/accounts/{account_id}/contacts/{contact_id}/labels` | List contact labels | Low | No |\n| `cap:chatwoot:contact.label.update` | `POST /api/v1/accounts/{account_id}/contacts/{contact_id}/labels` | Replace contact labels | Medium | Required |\n| `cap:chatwoot:contact.merge` | `POST /api/v1/accounts/{account_id}/actions/contact_merge` | Merge one contact into another | Medium | Required |\n| `cap:chatwoot:contact.contactable_inbox.list` | `GET /api/v1/accounts/{account_id}/contacts/{contact_id}/contactable_inboxes` | List attachable inboxes | Low | No |\n\n`contact.filter` is governed as a mutation because its provider method is\n`POST`. Use `contact.list`, `contact.active`, or `contact.search` when one of\nthose read contracts satisfies the task.\n\n`contact.merge` has no contact ID in its route. The provider body must identify\nthe source and destination contacts. The AIP contract declares no rollback or\ncompensating capability.\n\n## Contact-note operations\n\n| Capability | Provider request | Purpose | Risk | Approval |\n|---|---|---|---|---|\n| `cap:chatwoot:contact.note.list` | `GET /api/v1/accounts/{account_id}/contacts/{contact_id}/notes` | List contact notes | Low | No |\n| `cap:chatwoot:contact.note.create` | `POST /api/v1/accounts/{account_id}/contacts/{contact_id}/notes` | Create a note | Medium | Required |\n| `cap:chatwoot:contact.note.get` | `GET /api/v1/accounts/{account_id}/contacts/{contact_id}/notes/{note_id}` | Read one note | Low | No |\n| `cap:chatwoot:contact.note.update` | `PATCH /api/v1/accounts/{account_id}/contacts/{contact_id}/notes/{note_id}` | Update one note | Medium | Required |\n| `cap:chatwoot:contact.note.delete` | `DELETE /api/v1/accounts/{account_id}/contacts/{contact_id}/notes/{note_id}` | Delete one note | High | Required |\n\nNotes can contain free-form customer or operational detail. The restricted,\nPII-present, redaction-required contract applies even when the provider does\nnot label a field as sensitive.\n\n## Company and relationship operations\n\n| Capability | Provider request | Purpose | Risk | Approval |\n|---|---|---|---|---|\n| `cap:chatwoot:company.list` | `GET /api/v1/accounts/{account_id}/companies` | List companies | Low | No |\n| `cap:chatwoot:company.create` | `POST /api/v1/accounts/{account_id}/companies` | Create a company | Medium | Required |\n| `cap:chatwoot:company.get` | `GET /api/v1/accounts/{account_id}/companies/{company_id}` | Read one company | Low | No |\n| `cap:chatwoot:company.update` | `PATCH /api/v1/accounts/{account_id}/companies/{company_id}` | Update one company | Medium | Required |\n| `cap:chatwoot:company.delete` | `DELETE /api/v1/accounts/{account_id}/companies/{company_id}` | Delete one company | High | Required |\n| `cap:chatwoot:company.search` | `GET /api/v1/accounts/{account_id}/companies/search` | Search companies | Low | No |\n| `cap:chatwoot:company.contact.list` | `GET /api/v1/accounts/{account_id}/companies/{company_id}/contacts` | List linked contacts | Low | No |\n| `cap:chatwoot:company.contact.create` | `POST /api/v1/accounts/{account_id}/companies/{company_id}/contacts` | Attach a contact | Medium | Required |\n| `cap:chatwoot:company.contact.delete` | `DELETE /api/v1/accounts/{account_id}/companies/{company_id}/contacts/{contact_id}` | Detach a contact | High | Required |\n| `cap:chatwoot:company.conversation.list` | `GET /api/v1/accounts/{account_id}/companies/{company_id}/conversations` | List company conversations | Low | No |\n\n`company.contact.delete` removes a relationship through the frozen route. Its\ncatalogue description does not claim that the contact record itself is\ndeleted.\n\n## Account and path inputs\n\nThe connector inserts its configured `account_id`. Do not send an account ID\nin Action input.\n\n| Input | Used by |\n|---|---|\n| `contact_id` | Contact reads, updates, deletes, conversations, inbox association, labels, notes, contactable inboxes, and company-contact detach |\n| `note_id` | Contact-note get, update, and delete |\n| `company_id` | Company get, update, delete, contact, and conversation routes |\n\nEvery path value must be a non-blank string of at most 512 bytes without\ncontrol characters. Each value is encoded as one URL segment.\n\n`contact.merge`, `contact.import`, `contact.export`, and\n`contact.filter` use account-level routes without a contact path ID. Their\nprovider bodies own the selection or identity fields.\n\n## Generic provider input\n\nEvery operation accepts the common catalogue envelope:\n\n| Property | Connector boundary |\n|---|---|\n| `query` | Optional object; at most 128 keys; scalar values or bounded scalar arrays |\n| `body` | Optional object; at most 512 properties and 16 MiB encoded |\n| `multipart` | Optional bounded fields-and-files object instead of `body` |\n\nThe connector rejects `body` and `multipart` together. It does not validate\ncontact names, identifiers, email addresses, phone numbers, company\nattributes, merge participants, import columns, or export filters.\n\nUse the payload schema for the exact pinned provider route. Preserve one\ncanonical body with the approval record; do not add or normalize customer data\nafter approval.\n\n## Read one contact\n\nUse an ID returned by the configured account route:\n\n```sh\naipctl action call \\\n  \"$AIP_URL\" \\\n  cap:chatwoot:contact.get \\\n  --action-id act_chatwoot_contact_get_001 \\\n  --input '{\"contact_id\":\"205\"}'\n```\n\nThe connector calls:\n\n```text\nGET /api/v1/accounts/{configured_account_id}/contacts/205\n```\n\nThis low-risk read advertises safe retry and needs no capability-level human\napproval. It still returns restricted PII. Limit the response to the actor and\npurpose authorized by tenant policy.\n\n## Govern consequential customer-data changes\n\n| Operation class | Primary risk | Evidence before dispatch | Verification after dispatch |\n|---|---|---|---|\n| Create or update | Wrong or duplicate customer identity | Canonical provider body and intended account | Read the exact record |\n| Contact or company delete | Loss of customer data or relationships | Current object, dependencies, and deletion intent | Compare provider state and audit evidence |\n| Company-contact attach or detach | Wrong relationship | Both authoritative IDs and intended direction | List company contacts |\n| Contact-inbox association | Wrong channel relationship | Contact, inbox, and account identity | List contactable or actual provider state |\n| Label replacement | Unintended removal of existing labels | Complete intended replacement set | Read labels |\n| Import | Broad customer-data change | Source artifact identity, scope, mapping, and expected count | Reconcile provider result and sampled records |\n| Export | Disclosure of a broad PII set | Purpose, scope, destination, retention, and access | Verify artifact custody and provider result |\n| Merge | Loss of distinct identity and relationship history | Source, destination, collision review, and authoritative snapshots | Read destination and related objects |\n\nThe Rust catalogue does not publish a per-item transaction or partial-success\nmodel for import, export, or merge. A successful AIP response contains the\nprovider result but does not add an atomic rollback guarantee.\n\nDo not include a copy-ready import, export, or merge body from an unpinned API\nversion. The generic Rust schema is not enough to establish those fields.\n\n## Shared mutation contract\n\nAll 17 mutations declare:\n\n| Contract field | Value |\n|---|---|\n| Approval | Required; tenant-policy selector |\n| Approval validity | 900,000 ms |\n| Approval evidence | Reason, input snapshot, policy decision |\n| Idempotency | Required; external-account scope; 86,400,000 ms published TTL |\n| Connector retry | Not supported; unsafe |\n| Side effects | `write`, `external_network` |\n| Data | Restricted; contains PII; redaction required |\n| Execution | Synchronous; no async, streaming, or cancellation support |\n| Compensation | Rollback not supported |\n\nAn idempotency key binds one canonical intent. It does not prove provider\ndeduplication for imports, merges, creates, or relationship changes.\n\n## Result contract\n\nEvery successful catalogue call returns:\n\n```json\n{\n  \"http_status\": 200,\n  \"body\": {},\n  \"provider_request_id\": null\n}\n```\n\nThe connector parses JSON into `body`, returns `null` for an empty body, and\nwraps non-JSON bytes in a `text` object. It reads `provider_request_id` from\n`x-request-id` and then `x-runtime`.\n\nThe output schema does not freeze a contact, note, company, import, export, or\nmerge result shape. Validate the fields the application requires and tolerate\nadditional provider fields.\n\n## Failures and recovery\n\n| Failure code | Typical cause | Safe response |\n|---|---|---|\n| `connector.chatwoot.invalid_action` | Unknown or unadmitted operation, missing path ID, or malformed generic input | Refresh discovery or correct input before dispatch |\n| `connector.chatwoot.missing_idempotency_key` | Mutation lacks a valid key | Restore the key bound to the original body and intent |\n| `connector.chatwoot.authentication` | Provider returned `401` or `403` | Verify account route and credential revision |\n| `connector.chatwoot.remote_rejected` | Provider rejected fields or current state | Correct authoritative input before another Action |\n| `connector.chatwoot.remote_temporary` | Provider returned `429` or a server error | Retry a read within policy; reconcile a mutation |\n| `connector.chatwoot.transport` | Provider exchange failed | Retry a read within policy; treat mutation outcome as uncertain |\n| `connector.chatwoot.response_too_large` | Response crossed the active bound | Preserve evidence and reconcile a mutation |\n\nAll connector failures set `retryable: false`. The 14 read contracts\nseparately advertise safe retry.\n\nFor an uncertain create, import, merge, relationship change, or note write,\ninspect authoritative provider state before any new Action. For an uncertain\nexport, determine whether provider-side work or output already exists before\ninitiating another disclosure.\n\nFor an uncertain delete, absence alone may not explain when or why the object\ndisappeared. Correlate the original Action, provider request identity, audit\nevidence, and dependent objects.\n\n## Verify an integration\n\nRequire all of the following:\n\n- discovery admits the exact capability for the configured account;\n- path IDs and provider-body identities come from authoritative state;\n- contact merge binds distinct reviewed source and destination identities;\n- import and export approval records include bounded scope and artifact\n  handling;\n- every mutation has one retained idempotency key and exact input snapshot;\n- the completed result belongs to the submitted Action;\n- consequential changes are read back through the configured account;\n- customer fields, notes, relationships, exports, and provider errors follow\n  restricted-data redaction and retention policy;\n- uncertain mutations are reconciled instead of repeated.\n\nThese checks validate application handling. They do not establish provider\npayload compatibility, live customer-data correctness, or qualification.\n\n## Related documentation\n\n- [Chatwoot capability index](README.md)\n- [Conversations and messages](conversations-and-messages.md)\n- [Authentication and account isolation](../getting-started/authentication-and-account-isolation.md)\n- [Approvals and policy](../../../concepts/approvals-and-policy.md)\n- [Error reference](../../../reference/errors.md)\n",
    "text": "Chatwoot contacts and companies\n\nUse these 31 capabilities to find and maintain contacts, notes, companies, and\ntheir relationships. Treat every result as restricted customer data, including\nreads that need no human approval.\n\nThe catalogue freezes capability IDs, provider methods, paths, and AIP policy\ncontracts. It does not freeze provider-specific contact or company body fields.\n\nFamily at a glance\n\n| Group | Operations | Reads | Mutations | High risk |\n\n| Contact records and relationships | 16 | 7 | 9 | 3 |\n| Contact notes | 5 | 2 | 3 | 1 |\n| Companies and relationships | 10 | 5 | 5 | 2 |\n| Total | 31 | 14 | 17 | 6 |\n\nAll 31 capabilities are Tools. The method split is 14 GET, ten POST, three\nPATCH, and four DELETE operations.\n\nThe 14 reads are low risk. Eleven mutations are medium risk. The\ncontact.import and contact.export POST operations plus the four deletes are\nhigh risk.\n\nContact record and relationship operations\n\n| Capability | Provider request | Purpose | Risk | Approval |\n\n| cap:chatwoot:contact.list | GET /api/v1/accounts/{accountid}/contacts | List contacts | Low | No |\n| cap:chatwoot:contact.create | POST /api/v1/accounts/{accountid}/contacts | Create a contact | Medium | Required |\n| cap:chatwoot:contact.get | GET /api/v1/accounts/{accountid}/contacts/{contactid} | Read one contact | Low | No |\n| cap:chatwoot:contact.update | PATCH /api/v1/accounts/{accountid}/contacts/{contactid} | Update one contact | Medium | Required |\n| cap:chatwoot:contact.delete | DELETE /api/v1/accounts/{accountid}/contacts/{contactid} | Delete one contact | High | Required |\n| cap:chatwoot:contact.active | GET /api/v1/accounts/{accountid}/contacts/active | List active contacts | Low | No |\n| cap:chatwoot:contact.search | GET /api/v1/accounts/{accountid}/contacts/search | Search contacts | Low | No |\n| cap:chatwoot:contact.filter | POST /api/v1/accounts/{accountid}/contacts/filter | Filter contacts | Medium | Required |\n| cap:chatwoot:contact.import | POST /api/v1/accounts/{accountid}/contacts/import | Import contacts | High | Required |\n| cap:chatwoot:contact.export | POST /api/v1/accounts/{accountid}/contacts/export | Export contacts | High | Required |\n| cap:chatwoot:contact.conversation.list | GET /api/v1/accounts/{accountid}/contacts/{contactid}/conversations | List contact conversations | Low | No |\n| cap:chatwoot:contact.inbox.create | POST /api/v1/accounts/{accountid}/contacts/{contactid}/contactinboxes | Associate a contact with an inbox | Medium | Required |\n| cap:chatwoot:contact.label.list | GET /api/v1/accounts/{accountid}/contacts/{contactid}/labels | List contact labels | Low | No |\n| cap:chatwoot:contact.label.update | POST /api/v1/accounts/{accountid}/contacts/{contactid}/labels | Replace contact labels | Medium | Required |\n| cap:chatwoot:contact.merge | POST /api/v1/accounts/{accountid}/actions/contactmerge | Merge one contact into another | Medium | Required |\n| cap:chatwoot:contact.contactableinbox.list | GET /api/v1/accounts/{accountid}/contacts/{contactid}/contactableinboxes | List attachable inboxes | Low | No |\n\ncontact.filter is governed as a mutation because its provider method is\nPOST. Use contact.list, contact.active, or contact.search when one of\nthose read contracts satisfies the task.\n\ncontact.merge has no contact ID in its route. The provider body must identify\nthe source and destination contacts. The AIP contract declares no rollback or\ncompensating capability.\n\nContact-note operations\n\n| Capability | Provider request | Purpose | Risk | Approval |\n\n| cap:chatwoot:contact.note.list | GET /api/v1/accounts/{accountid}/contacts/{contactid}/notes | List contact notes | Low | No |\n| cap:chatwoot:contact.note.create | POST /api/v1/accounts/{accountid}/contacts/{contactid}/notes | Create a note | Medium | Required |\n| cap:chatwoot:contact.note.get | GET /api/v1/accounts/{accountid}/contacts/{contactid}/notes/{noteid} | Read one note | Low | No |\n| cap:chatwoot:contact.note.update | PATCH /api/v1/accounts/{accountid}/contacts/{contactid}/notes/{noteid} | Update one note | Medium | Required |\n| cap:chatwoot:contact.note.delete | DELETE /api/v1/accounts/{accountid}/contacts/{contactid}/notes/{noteid} | Delete one note | High | Required |\n\nNotes can contain free-form customer or operational detail. The restricted,\nPII-present, redaction-required contract applies even when the provider does\nnot label a field as sensitive.\n\nCompany and relationship operations\n\n| Capability | Provider request | Purpose | Risk | Approval |\n\n| cap:chatwoot:company.list | GET /api/v1/accounts/{accountid}/companies | List companies | Low | No |\n| cap:chatwoot:company.create | POST /api/v1/accounts/{accountid}/companies | Create a company | Medium | Required |\n| cap:chatwoot:company.get | GET /api/v1/accounts/{accountid}/companies/{companyid} | Read one company | Low | No |\n| cap:chatwoot:company.update | PATCH /api/v1/accounts/{accountid}/companies/{companyid} | Update one company | Medium | Required |\n| cap:chatwoot:company.delete | DELETE /api/v1/accounts/{accountid}/companies/{companyid} | Delete one company | High | Required |\n| cap:chatwoot:company.search | GET /api/v1/accounts/{accountid}/companies/search | Search companies | Low | No |\n| cap:chatwoot:company.contact.list | GET /api/v1/accounts/{accountid}/companies/{companyid}/contacts | List linked contacts | Low | No |\n| cap:chatwoot:company.contact.create | POST /api/v1/accounts/{accountid}/companies/{companyid}/contacts | Attach a contact | Medium | Required |\n| cap:chatwoot:company.contact.delete | DELETE /api/v1/accounts/{accountid}/companies/{companyid}/contacts/{contactid} | Detach a contact | High | Required |\n| cap:chatwoot:company.conversation.list | GET /api/v1/accounts/{accountid}/companies/{companyid}/conversations | List company conversations | Low | No |\n\ncompany.contact.delete removes a relationship through the frozen route. Its\ncatalogue description does not claim that the contact record itself is\ndeleted.\n\nAccount and path inputs\n\nThe connector inserts its configured accountid. Do not send an account ID\nin Action input.\n\n| Input | Used by |\n\n| contactid | Contact reads, updates, deletes, conversations, inbox association, labels, notes, contactable inboxes, and company-contact detach |\n| noteid | Contact-note get, update, and delete |\n| companyid | Company get, update, delete, contact, and conversation routes |\n\nEvery path value must be a non-blank string of at most 512 bytes without\ncontrol characters. Each value is encoded as one URL segment.\n\ncontact.merge, contact.import, contact.export, and\ncontact.filter use account-level routes without a contact path ID. Their\nprovider bodies own the selection or identity fields.\n\nGeneric provider input\n\nEvery operation accepts the common catalogue envelope:\n\n| Property | Connector boundary |\n\n| query | Optional object; at most 128 keys; scalar values or bounded scalar arrays |\n| body | Optional object; at most 512 properties and 16 MiB encoded |\n| multipart | Optional bounded fields-and-files object instead of body |\n\nThe connector rejects body and multipart together. It does not validate\ncontact names, identifiers, email addresses, phone numbers, company\nattributes, merge participants, import columns, or export filters.\n\nUse the payload schema for the exact pinned provider route. Preserve one\ncanonical body with the approval record; do not add or normalize customer data\nafter approval.\n\nRead one contact\n\nUse an ID returned by the configured account route:\n\naipctl action call \\\n  \"$AIPURL\" \\\n  cap:chatwoot:contact.get \\\n  --action-id actchatwootcontactget001 \\\n  --input '{\"contactid\":\"205\"}'\n\nThe connector calls:\n\nGET /api/v1/accounts/{configuredaccountid}/contacts/205\n\nThis low-risk read advertises safe retry and needs no capability-level human\napproval. It still returns restricted PII. Limit the response to the actor and\npurpose authorized by tenant policy.\n\nGovern consequential customer-data changes\n\n| Operation class | Primary risk | Evidence before dispatch | Verification after dispatch |\n\n| Create or update | Wrong or duplicate customer identity | Canonical provider body and intended account | Read the exact record |\n| Contact or company delete | Loss of customer data or relationships | Current object, dependencies, and deletion intent | Compare provider state and audit evidence |\n| Company-contact attach or detach | Wrong relationship | Both authoritative IDs and intended direction | List company contacts |\n| Contact-inbox association | Wrong channel relationship | Contact, inbox, and account identity | List contactable or actual provider state |\n| Label replacement | Unintended removal of existing labels | Complete intended replacement set | Read labels |\n| Import | Broad customer-data change | Source artifact identity, scope, mapping, and expected count | Reconcile provider result and sampled records |\n| Export | Disclosure of a broad PII set | Purpose, scope, destination, retention, and access | Verify artifact custody and provider result |\n| Merge | Loss of distinct identity and relationship history | Source, destination, collision review, and authoritative snapshots | Read destination and related objects |\n\nThe Rust catalogue does not publish a per-item transaction or partial-success\nmodel for import, export, or merge. A successful AIP response contains the\nprovider result but does not add an atomic rollback guarantee.\n\nDo not include a copy-ready import, export, or merge body from an unpinned API\nversion. The generic Rust schema is not enough to establish those fields.\n\nShared mutation contract\n\nAll 17 mutations declare:\n\n| Contract field | Value |\n\n| Approval | Required; tenant-policy selector |\n| Approval validity | 900,000 ms |\n| Approval evidence | Reason, input snapshot, policy decision |\n| Idempotency | Required; external-account scope; 86,400,000 ms published TTL |\n| Connector retry | Not supported; unsafe |\n| Side effects | write, externalnetwork |\n| Data | Restricted; contains PII; redaction required |\n| Execution | Synchronous; no async, streaming, or cancellation support |\n| Compensation | Rollback not supported |\n\nAn idempotency key binds one canonical intent. It does not prove provider\ndeduplication for imports, merges, creates, or relationship changes.\n\nResult contract\n\nEvery successful catalogue call returns:\n\n{\n  \"httpstatus\": 200,\n  \"body\": {},\n  \"providerrequestid\": null\n}\n\nThe connector parses JSON into body, returns null for an empty body, and\nwraps non-JSON bytes in a text object. It reads providerrequestid from\nx-request-id and then x-runtime.\n\nThe output schema does not freeze a contact, note, company, import, export, or\nmerge result shape. Validate the fields the application requires and tolerate\nadditional provider fields.\n\nFailures and recovery\n\n| Failure code | Typical cause | Safe response |\n\n| connector.chatwoot.invalidaction | Unknown or unadmitted operation, missing path ID, or malformed generic input | Refresh discovery or correct input before dispatch |\n| connector.chatwoot.missingidempotencykey | Mutation lacks a valid key | Restore the key bound to the original body and intent |\n| connector.chatwoot.authentication | Provider returned 401 or 403 | Verify account route and credential revision |\n| connector.chatwoot.remoterejected | Provider rejected fields or current state | Correct authoritative input before another Action |\n| connector.chatwoot.remotetemporary | Provider returned 429 or a server error | Retry a read within policy; reconcile a mutation |\n| connector.chatwoot.transport | Provider exchange failed | Retry a read within policy; treat mutation outcome as uncertain |\n| connector.chatwoot.responsetoolarge | Response crossed the active bound | Preserve evidence and reconcile a mutation |\n\nAll connector failures set retryable: false. The 14 read contracts\nseparately advertise safe retry.\n\nFor an uncertain create, import, merge, relationship change, or note write,\ninspect authoritative provider state before any new Action. For an uncertain\nexport, determine whether provider-side work or output already exists before\ninitiating another disclosure.\n\nFor an uncertain delete, absence alone may not explain when or why the object\ndisappeared. Correlate the original Action, provider request identity, audit\nevidence, and dependent objects.\n\nVerify an integration\n\nRequire all of the following:\n• discovery admits the exact capability for the configured account;\n• path IDs and provider-body identities come from authoritative state;\n• contact merge binds distinct reviewed source and destination identities;\n• import and export approval records include bounded scope and artifact\n  handling;\n• every mutation has one retained idempotency key and exact input snapshot;\n• the completed result belongs to the submitted Action;\n• consequential changes are read back through the configured account;\n• customer fields, notes, relationships, exports, and provider errors follow\n  restricted-data redaction and retention policy;\n• uncertain mutations are reconciled instead of repeated.\n\nThese checks validate application handling. They do not establish provider\npayload compatibility, live customer-data correctness, or qualification.\n\nRelated documentation\n• Chatwoot capability index (README.md)\n• Conversations and messages (conversations-and-messages.md)\n• Authentication and account isolation (../getting-started/authentication-and-account-isolation.md)\n• Approvals and policy (../../../concepts/approvals-and-policy.md)\n• Error reference (../../../reference/errors.md)\n"
  },
  "integrity": {
    "algorithm": "sha256",
    "sourceDigest": "d4d420a2222316158da8f2aa7837322eef1450021f3aed009ab9387d1643a448"
  }
}
