{
  "schemaVersion": "1.0",
  "title": "Chatwoot customer portals",
  "description": "Use these five capabilities to list and create help-center portals, update a portal, and create categories or articles inside a portal. The reviewed surface is intentionally smaller than full portal CRUD.",
  "canonical": "https://getaip.org/docs/connectors/chatwoot/capabilities/customer-portals",
  "route": "/docs/connectors/chatwoot/capabilities/customer-portals",
  "source": "docs/connectors/chatwoot/capabilities/customer-portals.md",
  "protocol": "Agent Interoperability Protocol",
  "protocolVersion": "1.0",
  "section": "Connectors",
  "documentType": "Connector",
  "language": "en",
  "downloads": {
    "md": "/docs/download/connectors/chatwoot/capabilities/customer-portals.md",
    "txt": "/docs/download/connectors/chatwoot/capabilities/customer-portals.txt",
    "json": "/docs/download/connectors/chatwoot/capabilities/customer-portals.json",
    "pdf": "/docs/download/connectors/chatwoot/capabilities/customer-portals.pdf"
  },
  "content": {
    "format": "text/markdown",
    "markdown": "---\ntitle: Chatwoot customer portals\ndescription: >-\n  Use five exact help-center capabilities with governed customer-visible\n  changes and an explicit partial-CRUD boundary\nkind: capability-reference\naudience: application-developer\nappliesTo: \"1.x\"\nwritingStandard: \"aip-docs/1.0\"\nlastReviewedRevision: \"97be86e9efedf07ecf1783b03800f683f107fb04\"\nconnector: chatwoot\ncapabilityIds:\n  - cap:chatwoot:portal.list\n  - cap:chatwoot:portal.create\n  - cap:chatwoot:portal.update\n  - cap:chatwoot:portal.category.create\n  - cap:chatwoot:portal.article.create\naliases:\n  - Chatwoot help-center capabilities\n  - Chatwoot portal operations\n---\n\n# Chatwoot customer portals\n\nUse these five capabilities to list and create help-center portals, update a\nportal, and create categories or articles inside a portal. The reviewed\nsurface is intentionally smaller than full portal CRUD.\n\nPortal content can become customer-visible. Review the provider body, intended\naudience, and publication behavior before approving a mutation.\n\n## Family at a glance\n\n| Operations | Reads | Mutations | High risk | Deletes |\n|---:|---:|---:|---:|---:|\n| 5 | 1 | 4 | 0 | 0 |\n\nAll five capabilities are Tools. `portal.list` is a low-risk `GET`. The three\n`POST` operations and one `PATCH` operation are medium-risk mutations.\n\nEvery mutation requires approval and an idempotency key. None advertises\nconnector retry support or compensation.\n\n## Operations\n\n| Capability | Provider request | Purpose | Risk | Approval |\n|---|---|---|---|---|\n| `cap:chatwoot:portal.list` | `GET /api/v1/accounts/{account_id}/portals` | List account help-center portals | Low | No |\n| `cap:chatwoot:portal.create` | `POST /api/v1/accounts/{account_id}/portals` | Create a help-center portal | Medium | Required |\n| `cap:chatwoot:portal.update` | `PATCH /api/v1/accounts/{account_id}/portals/{portal_id}` | Update a help-center portal | Medium | Required |\n| `cap:chatwoot:portal.category.create` | `POST /api/v1/accounts/{account_id}/portals/{portal_id}/categories` | Create a category | Medium | Required |\n| `cap:chatwoot:portal.article.create` | `POST /api/v1/accounts/{account_id}/portals/{portal_id}/articles` | Create an article | Medium | Required |\n\nThe provider path and operation description use help-center portal semantics.\nThese capabilities do not manage the AIP documentation site or connector-host\nHTTP routes.\n\n## Supported and absent operations\n\n| Object | Supported | Not present in the reviewed catalogue |\n|---|---|---|\n| Portal | List, create, update | Get by ID, delete |\n| Category | Create | List, get, update, delete |\n| Article | Create | List, get, update, delete |\n\nDo not synthesize an absent capability ID or call an arbitrary provider route.\nAdmission applies only to the five exact suffixes above.\n\nThe missing delete surface also limits recovery. A corrective provider\noperation outside this catalogue is not an AIP compensating capability and\nrequires a separate authorized path.\n\n## Account and path inputs\n\nThe connector inserts its configured `account_id` into every route. It is not\nan Action input.\n\n`portal_id` is required by:\n\n- `portal.update`;\n- `portal.category.create`;\n- `portal.article.create`.\n\nThe value must be a non-blank string of at most 512 bytes without control\ncharacters. The connector inserts it as one encoded path segment.\n\n`portal.list` and `portal.create` use the account collection route. Category\nand article identities belong to provider responses or bodies, not to an\ninvented path placeholder.\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\nportal names, domains, locales, visibility, category structure, article\ncontent, publication state, or other provider fields.\n\nUse the exact pinned provider schema. Retain one canonical body with the\napproval record; do not edit customer-visible content after approval.\n\n## List portals\n\nThis read needs no provider-specific path or body input:\n\n```sh\naipctl action call \\\n  \"$AIP_URL\" \\\n  cap:chatwoot:portal.list \\\n  --action-id act_chatwoot_portal_list_001 \\\n  --input '{}'\n```\n\nThe connector sends:\n\n```text\nGET /api/v1/accounts/{configured_account_id}/portals\n```\n\nThe read needs no capability-level approval and advertises safe retry. Its\nprovider body remains restricted and PII-present under the common contract.\n\nThe list result is the only portal read in this family. Confirm that its\nprovider shape contains the fields required for review before relying on it as\nan authoritative snapshot.\n\n## Review a portal mutation\n\n| Intent | Review before approval | Verify after completion |\n|---|---|---|\n| Create a portal | Exact provider body, account, audience, and expected visibility | Find the returned portal in the list |\n| Update a portal | Current list evidence, portal ID, changed fields, and visibility impact | List portals and compare the target |\n| Create a category | Portal identity, category body, hierarchy, and audience | Inspect the provider result and available portal state |\n| Create an article | Portal identity, article body, links, restricted data, and audience | Inspect the provider result and available portal state |\n\nThe source does not state whether a created object becomes visible\nimmediately. Treat publication behavior as provider-owned and verify it through\nthe pinned Chatwoot surface.\n\nDo not approve a guessed body. The generic schema proves only that the body is\na bounded JSON object.\n\n## Shared mutation contract\n\nAll four 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\nThe connector forwards the idempotency key to Chatwoot. The contract does not\nprove provider deduplication or content-level rollback.\n\n## Result contract\n\nEvery successful operation returns:\n\n```json\n{\n  \"http_status\": 200,\n  \"body\": {},\n  \"provider_request_id\": null\n}\n```\n\n`body` contains parsed JSON, `null` for an empty response, or a `text` wrapper\nfor non-JSON bytes. `provider_request_id` reads `x-request-id` first and\n`x-runtime` second.\n\nThe output schema does not freeze a portal, category, or article shape.\nValidate required provider fields and preserve unknown fields.\n\n## Failures and recovery\n\n| Failure code | Typical cause | Safe response |\n|---|---|---|\n| `connector.chatwoot.invalid_action` | Unknown or unadmitted ID, missing portal 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 for the original content 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 a new Action |\n| `connector.chatwoot.remote_temporary` | Provider returned `429` or a server error | Retry the list read within policy; reconcile a mutation |\n| `connector.chatwoot.transport` | Provider exchange failed | Retry the list 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`. Only `portal.list` advertises\nsafe retry.\n\nFor an uncertain create, list portals and inspect the original provider result\nevidence before another Action. Duplicate portal, category, or article creation\ncannot be repaired through a delete capability in this catalogue.\n\nFor an uncertain update, compare the target in the list when its shape permits.\nA corrective update needs new approval against current provider state.\n\n## Verify an integration\n\nRequire all of the following:\n\n- discovery admits one of the five exact portal capabilities;\n- the task does not depend on an absent get, update, or delete surface;\n- `portal_id` belongs to the configured account;\n- provider body fields and publication behavior come from the pinned API;\n- approval binds the exact customer-visible content and intended audience;\n- each mutation retains one Action, canonical input, and idempotency key;\n- available provider state confirms the completed change;\n- portal content and results follow restricted-data policy;\n- uncertain mutations are reconciled instead of repeated.\n\nThese checks validate application handling. They do not establish publication\nstate, provider payload compatibility, or live qualification.\n\n## Related documentation\n\n- [Chatwoot capability index](README.md)\n- [Automation, macros, and canned responses](automation-macros-and-canned-responses.md)\n- [Chatwoot connector configuration](../reference/configuration.md)\n- [Approvals and policy](../../../concepts/approvals-and-policy.md)\n- [Error reference](../../../reference/errors.md)\n",
    "text": "Chatwoot customer portals\n\nUse these five capabilities to list and create help-center portals, update a\nportal, and create categories or articles inside a portal. The reviewed\nsurface is intentionally smaller than full portal CRUD.\n\nPortal content can become customer-visible. Review the provider body, intended\naudience, and publication behavior before approving a mutation.\n\nFamily at a glance\n\n| Operations | Reads | Mutations | High risk | Deletes |\n\n| 5 | 1 | 4 | 0 | 0 |\n\nAll five capabilities are Tools. portal.list is a low-risk GET. The three\nPOST operations and one PATCH operation are medium-risk mutations.\n\nEvery mutation requires approval and an idempotency key. None advertises\nconnector retry support or compensation.\n\nOperations\n\n| Capability | Provider request | Purpose | Risk | Approval |\n\n| cap:chatwoot:portal.list | GET /api/v1/accounts/{accountid}/portals | List account help-center portals | Low | No |\n| cap:chatwoot:portal.create | POST /api/v1/accounts/{accountid}/portals | Create a help-center portal | Medium | Required |\n| cap:chatwoot:portal.update | PATCH /api/v1/accounts/{accountid}/portals/{portalid} | Update a help-center portal | Medium | Required |\n| cap:chatwoot:portal.category.create | POST /api/v1/accounts/{accountid}/portals/{portalid}/categories | Create a category | Medium | Required |\n| cap:chatwoot:portal.article.create | POST /api/v1/accounts/{accountid}/portals/{portalid}/articles | Create an article | Medium | Required |\n\nThe provider path and operation description use help-center portal semantics.\nThese capabilities do not manage the AIP documentation site or connector-host\nHTTP routes.\n\nSupported and absent operations\n\n| Object | Supported | Not present in the reviewed catalogue |\n\n| Portal | List, create, update | Get by ID, delete |\n| Category | Create | List, get, update, delete |\n| Article | Create | List, get, update, delete |\n\nDo not synthesize an absent capability ID or call an arbitrary provider route.\nAdmission applies only to the five exact suffixes above.\n\nThe missing delete surface also limits recovery. A corrective provider\noperation outside this catalogue is not an AIP compensating capability and\nrequires a separate authorized path.\n\nAccount and path inputs\n\nThe connector inserts its configured accountid into every route. It is not\nan Action input.\n\nportalid is required by:\n• portal.update;\n• portal.category.create;\n• portal.article.create.\n\nThe value must be a non-blank string of at most 512 bytes without control\ncharacters. The connector inserts it as one encoded path segment.\n\nportal.list and portal.create use the account collection route. Category\nand article identities belong to provider responses or bodies, not to an\ninvented path placeholder.\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\nportal names, domains, locales, visibility, category structure, article\ncontent, publication state, or other provider fields.\n\nUse the exact pinned provider schema. Retain one canonical body with the\napproval record; do not edit customer-visible content after approval.\n\nList portals\n\nThis read needs no provider-specific path or body input:\n\naipctl action call \\\n  \"$AIPURL\" \\\n  cap:chatwoot:portal.list \\\n  --action-id actchatwootportallist001 \\\n  --input '{}'\n\nThe connector sends:\n\nGET /api/v1/accounts/{configuredaccountid}/portals\n\nThe read needs no capability-level approval and advertises safe retry. Its\nprovider body remains restricted and PII-present under the common contract.\n\nThe list result is the only portal read in this family. Confirm that its\nprovider shape contains the fields required for review before relying on it as\nan authoritative snapshot.\n\nReview a portal mutation\n\n| Intent | Review before approval | Verify after completion |\n\n| Create a portal | Exact provider body, account, audience, and expected visibility | Find the returned portal in the list |\n| Update a portal | Current list evidence, portal ID, changed fields, and visibility impact | List portals and compare the target |\n| Create a category | Portal identity, category body, hierarchy, and audience | Inspect the provider result and available portal state |\n| Create an article | Portal identity, article body, links, restricted data, and audience | Inspect the provider result and available portal state |\n\nThe source does not state whether a created object becomes visible\nimmediately. Treat publication behavior as provider-owned and verify it through\nthe pinned Chatwoot surface.\n\nDo not approve a guessed body. The generic schema proves only that the body is\na bounded JSON object.\n\nShared mutation contract\n\nAll four 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\nThe connector forwards the idempotency key to Chatwoot. The contract does not\nprove provider deduplication or content-level rollback.\n\nResult contract\n\nEvery successful operation returns:\n\n{\n  \"httpstatus\": 200,\n  \"body\": {},\n  \"providerrequestid\": null\n}\n\nbody contains parsed JSON, null for an empty response, or a text wrapper\nfor non-JSON bytes. providerrequestid reads x-request-id first and\nx-runtime second.\n\nThe output schema does not freeze a portal, category, or article shape.\nValidate required provider fields and preserve unknown fields.\n\nFailures and recovery\n\n| Failure code | Typical cause | Safe response |\n\n| connector.chatwoot.invalidaction | Unknown or unadmitted ID, missing portal ID, or malformed generic input | Refresh discovery or correct input before dispatch |\n| connector.chatwoot.missingidempotencykey | Mutation lacks a valid key | Restore the key for the original content 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 a new Action |\n| connector.chatwoot.remotetemporary | Provider returned 429 or a server error | Retry the list read within policy; reconcile a mutation |\n| connector.chatwoot.transport | Provider exchange failed | Retry the list 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. Only portal.list advertises\nsafe retry.\n\nFor an uncertain create, list portals and inspect the original provider result\nevidence before another Action. Duplicate portal, category, or article creation\ncannot be repaired through a delete capability in this catalogue.\n\nFor an uncertain update, compare the target in the list when its shape permits.\nA corrective update needs new approval against current provider state.\n\nVerify an integration\n\nRequire all of the following:\n• discovery admits one of the five exact portal capabilities;\n• the task does not depend on an absent get, update, or delete surface;\n• portalid belongs to the configured account;\n• provider body fields and publication behavior come from the pinned API;\n• approval binds the exact customer-visible content and intended audience;\n• each mutation retains one Action, canonical input, and idempotency key;\n• available provider state confirms the completed change;\n• portal content and results follow restricted-data policy;\n• uncertain mutations are reconciled instead of repeated.\n\nThese checks validate application handling. They do not establish publication\nstate, provider payload compatibility, or live qualification.\n\nRelated documentation\n• Chatwoot capability index (README.md)\n• Automation, macros, and canned responses (automation-macros-and-canned-responses.md)\n• Chatwoot connector configuration (../reference/configuration.md)\n• Approvals and policy (../../../concepts/approvals-and-policy.md)\n• Error reference (../../../reference/errors.md)\n"
  },
  "integrity": {
    "algorithm": "sha256",
    "sourceDigest": "af6799a1428d520fbd2bded51d172ae2bed8ea029639f5188ce89e703fccd638"
  }
}
