{
  "schemaVersion": "1.0",
  "title": "Authenticate and isolate a Chatwoot account",
  "description": "Use this guide to bind one standalone Chatwoot host to one verified AIP tenant, one fixed provider origin, and one Chatwoot account. The API token stays in an owner-controlled file and is added to provider requests inside the connector.",
  "canonical": "https://getaip.org/docs/connectors/chatwoot/getting-started/authentication-and-account-isolation",
  "route": "/docs/connectors/chatwoot/getting-started/authentication-and-account-isolation",
  "source": "docs/connectors/chatwoot/getting-started/authentication-and-account-isolation.md",
  "protocol": "Agent Interoperability Protocol",
  "protocolVersion": "1.0",
  "section": "Connectors",
  "documentType": "Connector",
  "language": "en",
  "downloads": {
    "md": "/docs/download/connectors/chatwoot/getting-started/authentication-and-account-isolation.md",
    "txt": "/docs/download/connectors/chatwoot/getting-started/authentication-and-account-isolation.txt",
    "json": "/docs/download/connectors/chatwoot/getting-started/authentication-and-account-isolation.json",
    "pdf": "/docs/download/connectors/chatwoot/getting-started/authentication-and-account-isolation.pdf"
  },
  "content": {
    "format": "text/markdown",
    "markdown": "---\ntitle: Authenticate and isolate a Chatwoot account\ndescription: >-\n  Bind one verified AIP tenant to one fixed Chatwoot account and an owner-held\n  API token\nkind: how-to\naudience: operator\nappliesTo: \"1.x\"\nwritingStandard: \"aip-docs/1.0\"\nlastReviewedRevision: \"97be86e9efedf07ecf1783b03800f683f107fb04\"\nconnector: chatwoot\naliases:\n  - Chatwoot authentication\n  - Chatwoot account isolation\n  - Chatwoot API token\n---\n\n# Authenticate and isolate a Chatwoot account\n\nUse this guide to bind one standalone Chatwoot host to one verified AIP tenant,\none fixed provider origin, and one Chatwoot account. The API token stays in an\nowner-controlled file and is added to provider requests inside the connector.\n\nThe account is deployment identity, not Action input. A caller can provide\noperation-specific path, query, or body values, but it cannot select another\nChatwoot origin, account, token, or tenant.\n\n## Keep the credential layers separate\n\nFive values protect different boundaries. Do not reuse one value for another\nlayer.\n\n| Layer | Protects | Secret |\n|---|---|---|\n| Caller credential | Application to `aipd` | Yes |\n| Gateway signature | `aipd` to the connector host | The gateway signing key is secret |\n| Host credential revision | Route authorization before provider work | No provider secret bytes |\n| Chatwoot API token | Connector host to the fixed Chatwoot account | Yes |\n| Webhook HMAC secret | Chatwoot ingress to the host | Yes, and separate from the API token |\n\n`AIPCTL_NATIVE_BEARER_TOKEN_FILE` authenticates a caller to `aipd`. It must not\npoint to the Chatwoot API-token file. Likewise, credential revision metadata\ncan fence an admitted route, but it does not contain or replace the provider\ntoken.\n\n## Prerequisites\n\nBefore changing the binding, require:\n\n- one admitted Chatwoot connector version and instance;\n- one verified AIP tenant and membership;\n- one stable Chatwoot origin and account ID;\n- one provider token with only the permissions needed by admitted operations;\n- one owner-controlled secret mount readable by the host process;\n- exact host, gateway, control-plane, artifact, and registry identities;\n- a rollback window in which the old replica and token can remain valid.\n\nRecord the source revision, image digest, connector version, instance, replica,\ntenant, external account, provider account, and credential revision. Do not\nrecord the token value.\n\n## 1. Provision the provider token file\n\nCreate the token through the deployment's secret manager and mount it as a\nregular owner-controlled file. On Unix, any group or world permission bit\ncauses startup to fail.\n\nA representative permission shape is:\n\n```text\n-rw------- 1 <host-uid> <host-gid> ... /run/secrets/chatwoot-api-token\n```\n\nThe file must contain one non-empty UTF-8 value after surrounding ASCII\nwhitespace is removed. The Chatwoot host reads at most 16 KiB. The common\nreader rejects a symlink, non-regular file, replacement race, empty file, or\noversized file, and zeroizes its temporary string.\n\nDo not place the token in:\n\n- an Action, manifest, admission package, registry row, or capability input;\n- a command-line argument or ordinary environment variable;\n- a base URL, image layer, Compose file, log, or evidence bundle;\n- the non-secret credential ID, issuer, revision, or secret-provider reference;\n- the webhook-secret file.\n\n## 2. Configure the fixed provider boundary\n\nConfigure one origin, one account, and the token-file path:\n\n```text\nAIP_CHATWOOT_BASE_URL=https://support.example.test\nAIP_CHATWOOT_ACCOUNT_ID=account_primary\nAIP_CHATWOOT_API_TOKEN_FILE=/run/secrets/chatwoot-api-token\n```\n\nThe origin must:\n\n- use HTTPS, except for explicit loopback HTTP;\n- contain no username, password, path prefix, query, or fragment;\n- identify the deployment-owned Chatwoot service rather than an\n  Action-selected destination.\n\nThe connector does not follow redirects. It uses a 10-second connection\ntimeout, a 120-second request timeout, and adds `api_access_token` inside the\nhost process.\n\nThe account ID must contain 1 to 256 bytes, must not be blank after trimming,\nand must not contain control characters. Treat it as immutable instance\nownership metadata.\n\nEvery `{account_id}` segment in the frozen provider catalogue is replaced with\nthis configured value. The connector intentionally omits `account_id` from\nthose Action schemas.\n\n## 3. Bind the host to the same tenant and external account\n\nConfigure fleet identity separately from the provider token:\n\n```text\nAIP_CONNECTOR_HOST_TENANT_ID=tenant-support-production\nAIP_CONNECTOR_HOST_MEMBERSHIP_ID=membership-chatwoot-primary\nAIP_CONNECTOR_HOST_EXTERNAL_ACCOUNT_ID=account_primary\nAIP_CONNECTOR_HOST_EXTERNAL_ACCOUNT_SYSTEM=chatwoot\nAIP_CONNECTOR_HOST_SECRET_PROVIDER_REF=secret://production/chatwoot/primary\n```\n\nThe external-account ID and system must be present together or both absent.\nFor a tenant-owned Chatwoot instance, set both and make the external-account ID\nequal to `AIP_CHATWOOT_ACCOUNT_ID` through deployment policy.\n\nThe reviewed host validates the two settings independently. It does not compare\nthe external-account ID with the Chatwoot account ID automatically. Admission\nreview and deployment validation must detect a mismatch before routing is\nenabled.\n\nThe registry binding must associate only the intended tenant and admitted\nChatwoot capabilities with this instance. A signed Action cannot override the\nverified tenant or redirect the host to another configured account.\n\n## 4. Configure credential identity and revision fencing\n\nThe common host can attach a non-secret credential handle to its verified\nexecution context. Configure all four handle fields together:\n\n```text\nAIP_CONNECTOR_HOST_CREDENTIAL_ID=chatwoot-primary-provider\nAIP_CONNECTOR_HOST_CREDENTIAL_ISSUER=chatwoot-deployment\nAIP_CONNECTOR_HOST_CREDENTIAL_SCOPES=chatwoot:account.get,chatwoot:conversation.list\nAIP_CONNECTOR_HOST_CREDENTIAL_REVISION=chatwoot-primary-2026-07-27-01\nAIP_CONNECTOR_HOST_CREDENTIAL_POLICY_FILE=/run/config/chatwoot-credential-policy.json\n```\n\nThe ID, issuer, revision, and at least one non-empty scope are a unit. A partial\nhandle fails startup. Use exact admitted scopes; do not copy a wildcard from a\ncontrolled fixture into a real deployment.\n\nThe reloadable policy can deny the configured or pinned revision before a\nprovider side effect. An unreadable, invalid, or non-authorizing policy fails\nclosed. This mechanism does not hot-reload `AIP_CHATWOOT_API_TOKEN_FILE` and\ndoes not let an Action select a different token.\n\n## 5. Verify isolation before enabling mutations\n\nKeep new mutation bindings disabled while admitting and checking the host.\nVerify in this order:\n\n1. the host registers with the expected connector type, version, instance,\n   replica, artifact digest, tenant, and external account;\n2. the configured provider-account health read succeeds without printing the\n   token;\n3. discovery for the intended tenant contains the expected Chatwoot reads;\n4. `cap:chatwoot:account.get` completes through the normal signed gateway path;\n5. the returned account identity matches the deployment record;\n6. an unauthorized tenant has no eligible Chatwoot route;\n7. an Action cannot provide `account_id`, a provider origin, or credential\n   material;\n8. a revoked credential revision is denied before provider work.\n\nUse the deterministic quickstart for the source-owned read path. Do not begin\nverification with a message, handoff, delete, or other provider mutation.\n\nIf the account returned by the read differs from the deployment record, disable\nthe binding. Correct the provider account, external-account metadata, admission\nmaterial, or secret mount without weakening the equality check.\n\n## 6. Rotate the provider token\n\nThe Chatwoot token is read when the host process starts. Replacing the mounted\nfile under a running process is not a documented token reload.\n\nRotate with a bounded replica rollout:\n\n1. create a least-privilege replacement token for the same Chatwoot account;\n2. mount it at a new owner-controlled path without changing the old replica;\n3. allocate a new credential revision and host configuration revision;\n4. update the revision policy and admission material through their controlled\n   paths;\n5. start a replacement replica with the new token file;\n6. verify the account read and unauthorized-tenant isolation;\n7. route new assignments to the replacement and drain the old replica;\n8. revoke the old token only after in-flight work and rollback needs settle;\n9. retain identities, timestamps, checks, drain evidence, and revocation\n   evidence without retaining token bytes.\n\nDo not rotate by editing an Action, changing the account behind an unchanged\ninstance, or reusing one replica ID for two running processes.\n\n## Resolve authentication and isolation failures\n\n| Symptom | Decision |\n|---|---|\n| Token file is rejected | Check file type, ownership, mode, UTF-8 content, and 16 KiB bound without printing it |\n| Provider origin is rejected | Use an HTTPS origin with no credentials, path, query, or fragment |\n| Account ID is rejected | Supply a non-blank 1-to-256-byte value without control characters |\n| External-account configuration is rejected | Set ID and system together, then compare the ID with `AIP_CHATWOOT_ACCOUNT_ID` |\n| Credential handle is rejected | Configure ID, issuer, revision, and non-empty scopes together |\n| Revision policy denies the route | Keep mutations disabled and repair the policy or pinned revision |\n| Host registers but discovery is empty | Compare tenant, membership, admission, capability, and route policy before changing the token |\n| Account read returns `401` or `403` | Check token ownership, expiry, permissions, origin, and account; do not retry a mutation |\n| Provider returns a redirect | Correct the fixed origin or provider routing; credentials are not forwarded |\n| Returned account is unexpected | Disable the binding and reconcile provider account with external-account metadata |\n\n## Related documentation\n\n- [Chatwoot connector overview](../README.md)\n- [Chatwoot connector quickstart](quickstart.md)\n- [Rotate connector credentials](../../../guides/connector-credentials-and-rotation.md)\n- [Connector registry and routing](../../../architecture/connector-registry-and-routing.md)\n- [Security model](../../../architecture/security-model.md)\n",
    "text": "Authenticate and isolate a Chatwoot account\n\nUse this guide to bind one standalone Chatwoot host to one verified AIP tenant,\none fixed provider origin, and one Chatwoot account. The API token stays in an\nowner-controlled file and is added to provider requests inside the connector.\n\nThe account is deployment identity, not Action input. A caller can provide\noperation-specific path, query, or body values, but it cannot select another\nChatwoot origin, account, token, or tenant.\n\nKeep the credential layers separate\n\nFive values protect different boundaries. Do not reuse one value for another\nlayer.\n\n| Layer | Protects | Secret |\n\n| Caller credential | Application to aipd | Yes |\n| Gateway signature | aipd to the connector host | The gateway signing key is secret |\n| Host credential revision | Route authorization before provider work | No provider secret bytes |\n| Chatwoot API token | Connector host to the fixed Chatwoot account | Yes |\n| Webhook HMAC secret | Chatwoot ingress to the host | Yes, and separate from the API token |\n\nAIPCTLNATIVEBEARERTOKENFILE authenticates a caller to aipd. It must not\npoint to the Chatwoot API-token file. Likewise, credential revision metadata\ncan fence an admitted route, but it does not contain or replace the provider\ntoken.\n\nPrerequisites\n\nBefore changing the binding, require:\n• one admitted Chatwoot connector version and instance;\n• one verified AIP tenant and membership;\n• one stable Chatwoot origin and account ID;\n• one provider token with only the permissions needed by admitted operations;\n• one owner-controlled secret mount readable by the host process;\n• exact host, gateway, control-plane, artifact, and registry identities;\n• a rollback window in which the old replica and token can remain valid.\n\nRecord the source revision, image digest, connector version, instance, replica,\ntenant, external account, provider account, and credential revision. Do not\nrecord the token value.\n1. Provision the provider token file\n\nCreate the token through the deployment's secret manager and mount it as a\nregular owner-controlled file. On Unix, any group or world permission bit\ncauses startup to fail.\n\nA representative permission shape is:\n\n-rw------- 1   ... /run/secrets/chatwoot-api-token\n\nThe file must contain one non-empty UTF-8 value after surrounding ASCII\nwhitespace is removed. The Chatwoot host reads at most 16 KiB. The common\nreader rejects a symlink, non-regular file, replacement race, empty file, or\noversized file, and zeroizes its temporary string.\n\nDo not place the token in:\n• an Action, manifest, admission package, registry row, or capability input;\n• a command-line argument or ordinary environment variable;\n• a base URL, image layer, Compose file, log, or evidence bundle;\n• the non-secret credential ID, issuer, revision, or secret-provider reference;\n• the webhook-secret file.\n2. Configure the fixed provider boundary\n\nConfigure one origin, one account, and the token-file path:\n\nAIPCHATWOOTBASEURL=https://support.example.test\nAIPCHATWOOTACCOUNTID=accountprimary\nAIPCHATWOOTAPITOKENFILE=/run/secrets/chatwoot-api-token\n\nThe origin must:\n• use HTTPS, except for explicit loopback HTTP;\n• contain no username, password, path prefix, query, or fragment;\n• identify the deployment-owned Chatwoot service rather than an\n  Action-selected destination.\n\nThe connector does not follow redirects. It uses a 10-second connection\ntimeout, a 120-second request timeout, and adds apiaccesstoken inside the\nhost process.\n\nThe account ID must contain 1 to 256 bytes, must not be blank after trimming,\nand must not contain control characters. Treat it as immutable instance\nownership metadata.\n\nEvery {accountid} segment in the frozen provider catalogue is replaced with\nthis configured value. The connector intentionally omits accountid from\nthose Action schemas.\n3. Bind the host to the same tenant and external account\n\nConfigure fleet identity separately from the provider token:\n\nAIPCONNECTORHOSTTENANTID=tenant-support-production\nAIPCONNECTORHOSTMEMBERSHIPID=membership-chatwoot-primary\nAIPCONNECTORHOSTEXTERNALACCOUNTID=accountprimary\nAIPCONNECTORHOSTEXTERNALACCOUNTSYSTEM=chatwoot\nAIPCONNECTORHOSTSECRETPROVIDERREF=secret://production/chatwoot/primary\n\nThe external-account ID and system must be present together or both absent.\nFor a tenant-owned Chatwoot instance, set both and make the external-account ID\nequal to AIPCHATWOOTACCOUNTID through deployment policy.\n\nThe reviewed host validates the two settings independently. It does not compare\nthe external-account ID with the Chatwoot account ID automatically. Admission\nreview and deployment validation must detect a mismatch before routing is\nenabled.\n\nThe registry binding must associate only the intended tenant and admitted\nChatwoot capabilities with this instance. A signed Action cannot override the\nverified tenant or redirect the host to another configured account.\n4. Configure credential identity and revision fencing\n\nThe common host can attach a non-secret credential handle to its verified\nexecution context. Configure all four handle fields together:\n\nAIPCONNECTORHOSTCREDENTIALID=chatwoot-primary-provider\nAIPCONNECTORHOSTCREDENTIALISSUER=chatwoot-deployment\nAIPCONNECTORHOSTCREDENTIALSCOPES=chatwoot:account.get,chatwoot:conversation.list\nAIPCONNECTORHOSTCREDENTIALREVISION=chatwoot-primary-2026-07-27-01\nAIPCONNECTORHOSTCREDENTIALPOLICYFILE=/run/config/chatwoot-credential-policy.json\n\nThe ID, issuer, revision, and at least one non-empty scope are a unit. A partial\nhandle fails startup. Use exact admitted scopes; do not copy a wildcard from a\ncontrolled fixture into a real deployment.\n\nThe reloadable policy can deny the configured or pinned revision before a\nprovider side effect. An unreadable, invalid, or non-authorizing policy fails\nclosed. This mechanism does not hot-reload AIPCHATWOOTAPITOKENFILE and\ndoes not let an Action select a different token.\n5. Verify isolation before enabling mutations\n\nKeep new mutation bindings disabled while admitting and checking the host.\nVerify in this order:\n1. the host registers with the expected connector type, version, instance,\n   replica, artifact digest, tenant, and external account;\n2. the configured provider-account health read succeeds without printing the\n   token;\n3. discovery for the intended tenant contains the expected Chatwoot reads;\n4. cap:chatwoot:account.get completes through the normal signed gateway path;\n5. the returned account identity matches the deployment record;\n6. an unauthorized tenant has no eligible Chatwoot route;\n7. an Action cannot provide accountid, a provider origin, or credential\n   material;\n8. a revoked credential revision is denied before provider work.\n\nUse the deterministic quickstart for the source-owned read path. Do not begin\nverification with a message, handoff, delete, or other provider mutation.\n\nIf the account returned by the read differs from the deployment record, disable\nthe binding. Correct the provider account, external-account metadata, admission\nmaterial, or secret mount without weakening the equality check.\n6. Rotate the provider token\n\nThe Chatwoot token is read when the host process starts. Replacing the mounted\nfile under a running process is not a documented token reload.\n\nRotate with a bounded replica rollout:\n1. create a least-privilege replacement token for the same Chatwoot account;\n2. mount it at a new owner-controlled path without changing the old replica;\n3. allocate a new credential revision and host configuration revision;\n4. update the revision policy and admission material through their controlled\n   paths;\n5. start a replacement replica with the new token file;\n6. verify the account read and unauthorized-tenant isolation;\n7. route new assignments to the replacement and drain the old replica;\n8. revoke the old token only after in-flight work and rollback needs settle;\n9. retain identities, timestamps, checks, drain evidence, and revocation\n   evidence without retaining token bytes.\n\nDo not rotate by editing an Action, changing the account behind an unchanged\ninstance, or reusing one replica ID for two running processes.\n\nResolve authentication and isolation failures\n\n| Symptom | Decision |\n\n| Token file is rejected | Check file type, ownership, mode, UTF-8 content, and 16 KiB bound without printing it |\n| Provider origin is rejected | Use an HTTPS origin with no credentials, path, query, or fragment |\n| Account ID is rejected | Supply a non-blank 1-to-256-byte value without control characters |\n| External-account configuration is rejected | Set ID and system together, then compare the ID with AIPCHATWOOTACCOUNTID |\n| Credential handle is rejected | Configure ID, issuer, revision, and non-empty scopes together |\n| Revision policy denies the route | Keep mutations disabled and repair the policy or pinned revision |\n| Host registers but discovery is empty | Compare tenant, membership, admission, capability, and route policy before changing the token |\n| Account read returns 401 or 403 | Check token ownership, expiry, permissions, origin, and account; do not retry a mutation |\n| Provider returns a redirect | Correct the fixed origin or provider routing; credentials are not forwarded |\n| Returned account is unexpected | Disable the binding and reconcile provider account with external-account metadata |\n\nRelated documentation\n• Chatwoot connector overview (../README.md)\n• Chatwoot connector quickstart (quickstart.md)\n• Rotate connector credentials (../../../guides/connector-credentials-and-rotation.md)\n• Connector registry and routing (../../../architecture/connector-registry-and-routing.md)\n• Security model (../../../architecture/security-model.md)\n"
  },
  "integrity": {
    "algorithm": "sha256",
    "sourceDigest": "a266272c9a288b932de9009bd1a2f9a2d66114a13d18550a7bac14f5be648569"
  }
}
