> For the complete documentation index, see [llms.txt](https://developer.celigo.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.celigo.com/api/api-reference/users.md).

# Users

Manage user access to a Celigo account. Each record represents a user's access grant, including their access level and invitation status.

Access is controlled at two levels:

* **accessLevel** — account-wide role (administrator, manage, monitor, etc.)
* **integrationAccessLevel** — per-integration overrides for finer control.

The account owner is not included — only invited users appear. Users can be disabled (reversible) or permanently removed.

### User schema

## The User object

```json
{"openapi":"3.2.0","info":{"title":"Users","version":"1.0.0"},"components":{"schemas":{"User":{"type":"object","required":["_id","integrationAccessLevel","createdAt","lastModified"],"description":"A user's access record in the account. Each user who has been invited\n(or shared access) gets one record per account they belong to. The\n`_id` is the access-record id, not the user's own id — the user's\nidentity is in `sharedWithUser._id` on list and invite responses, and\nin `_sharedWithUserId` on `GET /v1/ashares/{_id}`. The account owner\ndoes not appear in this list.","allOf":[{"$ref":"#/components/schemas/UserBase"},{"type":"object","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Access-record id for this user in the account."},"_sharedWithUserId":{"type":"string","format":"objectId","readOnly":true,"description":"The user's own account id. Present on `GET /v1/ashares/{_id}`, which\nreturns the bare record; the list and invite responses expand it into\n`sharedWithUser` instead."},"accepted":{"type":"boolean","readOnly":true,"description":"When true, the user has accepted the invitation to join the account."},"disabled":{"type":"boolean","readOnly":true,"description":"When true, the user's access to the account is suspended. Changed\nonly by `PUT /v1/ashares/{_userId}/disable` — a value sent on the\nupdate operation is accepted but not applied."},"userType":{"type":"string","readOnly":true,"enum":["workspace"],"description":"Discriminates workspace users from end users on the underlying\naccess-record model. Reads on this API return only `workspace`\nrecords — end users are managed through the End Users API, which\nshares the update and disable routes. Sending it back on update\nis rejected."},"lastSignIn":{"type":"string","format":"date-time","readOnly":true,"description":"When the user last signed in to this account."},"dismissed":{"type":"boolean","readOnly":true,"description":"When true, the invitation has been declined by the user."},"isProductionAdmin":{"type":"boolean","readOnly":true,"description":"When true, the user has production-admin privileges in this account."},"createdVia":{"type":"string","readOnly":true,"description":"How this user's access record was created.","enum":["existing_account_invite","existing_account_share_request","invited_during_signup","new_account_auto_join"]},"ssoSetupPending":{"type":"boolean","readOnly":true,"description":"When true, the user must complete SSO setup for this account\nbefore their SSO-required access is fully active. Set by the\nserver during SSO enrollment; cleared by removing the field, so\nit is never `false`."},"sharedWithUser":{"type":"object","readOnly":true,"description":"Identity details of the invited/shared user. Present on the list and\ninvite responses; `GET /v1/ashares/{_id}` returns `_sharedWithUserId`\nin its place.","properties":{"_id":{"type":"string","format":"objectId","description":"The user's own account id."},"email":{"type":"string","format":"email","description":"Email address of the user."},"name":{"type":"string","description":"Display name of the user."},"lastSignIn":{"type":"string","format":"date-time","description":"When the user last signed in (across any account)."},"allowedToResetMFA":{"type":"boolean","description":"When true, the current requester can reset MFA for this user."},"accountSSOLinked":{"type":"string","description":"SSO linkage status for the user in this account.\n`this_account` means SSO is linked to the current account.\n`other_account` means SSO is linked to a different account.","enum":["not_linked","this_account","other_account"]}}}}},{"$ref":"#/components/schemas/ResourceResponse"}]},"UserBase":{"type":"object","description":"Writable fields shared by the request and response schemas.","properties":{"accessLevel":{"type":"string","description":"Account-level access for the user.\n\n**CRITICAL**: This controls account-wide access. Choose your strategy:\n\n- Integration-only access: omit `accessLevel` and specify integrations in `integrationAccessLevel`\n- Account-wide monitoring + selective management: set `accessLevel: monitor` and use `integrationAccessLevel`\n  to grant `manage` access for specific integrations\n- Full account access: set `accessLevel: manage` or `accessLevel: administrator` and leave\n  `integrationAccessLevel` undefined/empty\n\nIf per-integration level permissions are needed, omit `accessLevel` and instead populate `integrationAccessLevel`.\n\nOn update (`PUT /v1/ashares/{_id}`) the body replaces the access settings: `integrationAccessLevel`\nand `accountMFARequired` are cleared when omitted, so resend them to keep them. `accountSSORequired`\nis different — it changes only when the body carries it.\n\n`none` is written by SCIM provisioning for a user who has no account-wide grant; do not send it\nyourself — omit `accessLevel` and use `integrationAccessLevel` for integration-only access.","enum":["monitor","manage","administrator","none"]},"integrationAccessLevel":{"type":"array","description":"Per-integration access levels for the user.\n\nUse this for granting access to specific integrations.\n\n- If `accessLevel` is omitted, this creates **integration-only** access.\n- If `accessLevel` is `monitor`, this grants **elevated access** (typically `manage`) for specific integrations.\n- If `accessLevel` is `manage` or `administrator`, do not set `integrationAccessLevel`.\n\nCleared when omitted on update — send `[]` explicitly only when you mean no per-integration grants.","items":{"type":"object","properties":{"_integrationId":{"type":"string","format":"objectId","description":"Integration ID the user should have access to."},"accessLevel":{"type":"string","description":"Access level for this integration.","enum":["monitor","manage"]}}}},"accountSSORequired":{"type":"boolean","description":"When true, the user must sign in through SSO to access this account. Written\nonly when present in the update body — omitting it on `PUT /v1/ashares/{_id}`\nleaves the stored value unchanged. While the account enforces SSO for every\nuser, the value sent is ignored and the stored value is kept until that\nenforcement is turned off."},"accountMFARequired":{"type":"boolean","description":"When true, MFA is required for this user in this account. Cleared when\nomitted on update — resend it with every `PUT /v1/ashares/{_id}`."},"allowAccessToAPIM":{"type":"boolean","description":"When true, the user can access API Management (APIM) features for this account."},"allowToEditRetryData":{"type":"boolean","description":"When true, the user can edit retry data when troubleshooting flow run errors (Error Management).\n\nAll users with **Monitor** access can view, retry, and resolve errant records. This flag controls whether they\ncan also **edit the retry data payload**. If set to false, the user cannot edit retry data for flow runs in any\nintegration workspace where they only have **Monitor** access.\n\nThis setting only applies when:\n- `accessLevel` is `monitor`, or\n- an entry in `integrationAccessLevel` grants `monitor` access for a specific integration."},"allowIntegrationWorkspaceCreation":{"type":"boolean","description":"When true, the user can create integration workspaces."}}},"ResourceResponse":{"type":"object","description":"Response","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource. Format is a 24-character hexadecimal string."},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was created. Set automatically and cannot be modified."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was last updated. Changes whenever any property is modified."},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp when the resource was soft-deleted. When null or absent, the resource is active."}},"required":["_id"]}}}}
```

## List users

> Returns all users with access to the account. The account owner is\
> not included — only invited users appear.

```json
{"openapi":"3.2.0","info":{"title":"Users","version":"1.0.0"},"tags":[{"name":"Users","description":"Manage user access to a Celigo account. Each record represents a user's\naccess grant, including their access level and invitation status.\n\nAccess is controlled at two levels:\n- **accessLevel** — account-wide role (administrator, manage, monitor, etc.)\n- **integrationAccessLevel** — per-integration overrides for finer control.\n\nThe account owner is not included — only invited users appear. Users can\nbe disabled (reversible) or permanently removed.\n\n## User schema\n\n{% openapi-schemas spec=\"user\" schemas=\"User\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"User":{"type":"object","required":["_id","integrationAccessLevel","createdAt","lastModified"],"description":"A user's access record in the account. Each user who has been invited\n(or shared access) gets one record per account they belong to. The\n`_id` is the access-record id, not the user's own id — the user's\nidentity is in `sharedWithUser._id` on list and invite responses, and\nin `_sharedWithUserId` on `GET /v1/ashares/{_id}`. The account owner\ndoes not appear in this list.","allOf":[{"$ref":"#/components/schemas/UserBase"},{"type":"object","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Access-record id for this user in the account."},"_sharedWithUserId":{"type":"string","format":"objectId","readOnly":true,"description":"The user's own account id. Present on `GET /v1/ashares/{_id}`, which\nreturns the bare record; the list and invite responses expand it into\n`sharedWithUser` instead."},"accepted":{"type":"boolean","readOnly":true,"description":"When true, the user has accepted the invitation to join the account."},"disabled":{"type":"boolean","readOnly":true,"description":"When true, the user's access to the account is suspended. Changed\nonly by `PUT /v1/ashares/{_userId}/disable` — a value sent on the\nupdate operation is accepted but not applied."},"userType":{"type":"string","readOnly":true,"enum":["workspace"],"description":"Discriminates workspace users from end users on the underlying\naccess-record model. Reads on this API return only `workspace`\nrecords — end users are managed through the End Users API, which\nshares the update and disable routes. Sending it back on update\nis rejected."},"lastSignIn":{"type":"string","format":"date-time","readOnly":true,"description":"When the user last signed in to this account."},"dismissed":{"type":"boolean","readOnly":true,"description":"When true, the invitation has been declined by the user."},"isProductionAdmin":{"type":"boolean","readOnly":true,"description":"When true, the user has production-admin privileges in this account."},"createdVia":{"type":"string","readOnly":true,"description":"How this user's access record was created.","enum":["existing_account_invite","existing_account_share_request","invited_during_signup","new_account_auto_join"]},"ssoSetupPending":{"type":"boolean","readOnly":true,"description":"When true, the user must complete SSO setup for this account\nbefore their SSO-required access is fully active. Set by the\nserver during SSO enrollment; cleared by removing the field, so\nit is never `false`."},"sharedWithUser":{"type":"object","readOnly":true,"description":"Identity details of the invited/shared user. Present on the list and\ninvite responses; `GET /v1/ashares/{_id}` returns `_sharedWithUserId`\nin its place.","properties":{"_id":{"type":"string","format":"objectId","description":"The user's own account id."},"email":{"type":"string","format":"email","description":"Email address of the user."},"name":{"type":"string","description":"Display name of the user."},"lastSignIn":{"type":"string","format":"date-time","description":"When the user last signed in (across any account)."},"allowedToResetMFA":{"type":"boolean","description":"When true, the current requester can reset MFA for this user."},"accountSSOLinked":{"type":"string","description":"SSO linkage status for the user in this account.\n`this_account` means SSO is linked to the current account.\n`other_account` means SSO is linked to a different account.","enum":["not_linked","this_account","other_account"]}}}}},{"$ref":"#/components/schemas/ResourceResponse"}]},"UserBase":{"type":"object","description":"Writable fields shared by the request and response schemas.","properties":{"accessLevel":{"type":"string","description":"Account-level access for the user.\n\n**CRITICAL**: This controls account-wide access. Choose your strategy:\n\n- Integration-only access: omit `accessLevel` and specify integrations in `integrationAccessLevel`\n- Account-wide monitoring + selective management: set `accessLevel: monitor` and use `integrationAccessLevel`\n  to grant `manage` access for specific integrations\n- Full account access: set `accessLevel: manage` or `accessLevel: administrator` and leave\n  `integrationAccessLevel` undefined/empty\n\nIf per-integration level permissions are needed, omit `accessLevel` and instead populate `integrationAccessLevel`.\n\nOn update (`PUT /v1/ashares/{_id}`) the body replaces the access settings: `integrationAccessLevel`\nand `accountMFARequired` are cleared when omitted, so resend them to keep them. `accountSSORequired`\nis different — it changes only when the body carries it.\n\n`none` is written by SCIM provisioning for a user who has no account-wide grant; do not send it\nyourself — omit `accessLevel` and use `integrationAccessLevel` for integration-only access.","enum":["monitor","manage","administrator","none"]},"integrationAccessLevel":{"type":"array","description":"Per-integration access levels for the user.\n\nUse this for granting access to specific integrations.\n\n- If `accessLevel` is omitted, this creates **integration-only** access.\n- If `accessLevel` is `monitor`, this grants **elevated access** (typically `manage`) for specific integrations.\n- If `accessLevel` is `manage` or `administrator`, do not set `integrationAccessLevel`.\n\nCleared when omitted on update — send `[]` explicitly only when you mean no per-integration grants.","items":{"type":"object","properties":{"_integrationId":{"type":"string","format":"objectId","description":"Integration ID the user should have access to."},"accessLevel":{"type":"string","description":"Access level for this integration.","enum":["monitor","manage"]}}}},"accountSSORequired":{"type":"boolean","description":"When true, the user must sign in through SSO to access this account. Written\nonly when present in the update body — omitting it on `PUT /v1/ashares/{_id}`\nleaves the stored value unchanged. While the account enforces SSO for every\nuser, the value sent is ignored and the stored value is kept until that\nenforcement is turned off."},"accountMFARequired":{"type":"boolean","description":"When true, MFA is required for this user in this account. Cleared when\nomitted on update — resend it with every `PUT /v1/ashares/{_id}`."},"allowAccessToAPIM":{"type":"boolean","description":"When true, the user can access API Management (APIM) features for this account."},"allowToEditRetryData":{"type":"boolean","description":"When true, the user can edit retry data when troubleshooting flow run errors (Error Management).\n\nAll users with **Monitor** access can view, retry, and resolve errant records. This flag controls whether they\ncan also **edit the retry data payload**. If set to false, the user cannot edit retry data for flow runs in any\nintegration workspace where they only have **Monitor** access.\n\nThis setting only applies when:\n- `accessLevel` is `monitor`, or\n- an entry in `integrationAccessLevel` grants `monitor` access for a specific integration."},"allowIntegrationWorkspaceCreation":{"type":"boolean","description":"When true, the user can create integration workspaces."}}},"ResourceResponse":{"type":"object","description":"Response","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource. Format is a 24-character hexadecimal string."},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was created. Set automatically and cannot be modified."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was last updated. Changes whenever any property is modified."},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp when the resource was soft-deleted. When null or absent, the resource is active."}},"required":["_id"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/ashares":{"get":{"summary":"List users","description":"Returns all users with access to the account. The account owner is\nnot included — only invited users appear.","operationId":"listUsers","tags":["Users"],"parameters":[{"name":"userType","in":"query","required":false,"schema":{"type":"string","enum":["workspace","end-user"]},"description":"Filter by access-record type. `workspace` returns the same records as\nan unfiltered call; `end-user` always returns 204 because end users\nare served by the End Users API, not this endpoint."}],"responses":{"200":{"description":"All users with access to the account.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/User"}}}}},"204":{"description":"No users exist in the account"},"401":{"$ref":"#/components/responses/401-unauthorized"}}}}}}
```

## Get a user

> Retrieve a single user's access record by its id. Returns the bare record:\
> the user is identified by \`\_sharedWithUserId\` rather than the expanded\
> \`sharedWithUser\` the list returns, and \`isProductionAdmin\` is not computed.\
> Returns workspace records only — an end-user access-record id is not found\
> here; read those from \`GET /v1/endusers\`.

```json
{"openapi":"3.2.0","info":{"title":"Users","version":"1.0.0"},"tags":[{"name":"Users","description":"Manage user access to a Celigo account. Each record represents a user's\naccess grant, including their access level and invitation status.\n\nAccess is controlled at two levels:\n- **accessLevel** — account-wide role (administrator, manage, monitor, etc.)\n- **integrationAccessLevel** — per-integration overrides for finer control.\n\nThe account owner is not included — only invited users appear. Users can\nbe disabled (reversible) or permanently removed.\n\n## User schema\n\n{% openapi-schemas spec=\"user\" schemas=\"User\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"User":{"type":"object","required":["_id","integrationAccessLevel","createdAt","lastModified"],"description":"A user's access record in the account. Each user who has been invited\n(or shared access) gets one record per account they belong to. The\n`_id` is the access-record id, not the user's own id — the user's\nidentity is in `sharedWithUser._id` on list and invite responses, and\nin `_sharedWithUserId` on `GET /v1/ashares/{_id}`. The account owner\ndoes not appear in this list.","allOf":[{"$ref":"#/components/schemas/UserBase"},{"type":"object","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Access-record id for this user in the account."},"_sharedWithUserId":{"type":"string","format":"objectId","readOnly":true,"description":"The user's own account id. Present on `GET /v1/ashares/{_id}`, which\nreturns the bare record; the list and invite responses expand it into\n`sharedWithUser` instead."},"accepted":{"type":"boolean","readOnly":true,"description":"When true, the user has accepted the invitation to join the account."},"disabled":{"type":"boolean","readOnly":true,"description":"When true, the user's access to the account is suspended. Changed\nonly by `PUT /v1/ashares/{_userId}/disable` — a value sent on the\nupdate operation is accepted but not applied."},"userType":{"type":"string","readOnly":true,"enum":["workspace"],"description":"Discriminates workspace users from end users on the underlying\naccess-record model. Reads on this API return only `workspace`\nrecords — end users are managed through the End Users API, which\nshares the update and disable routes. Sending it back on update\nis rejected."},"lastSignIn":{"type":"string","format":"date-time","readOnly":true,"description":"When the user last signed in to this account."},"dismissed":{"type":"boolean","readOnly":true,"description":"When true, the invitation has been declined by the user."},"isProductionAdmin":{"type":"boolean","readOnly":true,"description":"When true, the user has production-admin privileges in this account."},"createdVia":{"type":"string","readOnly":true,"description":"How this user's access record was created.","enum":["existing_account_invite","existing_account_share_request","invited_during_signup","new_account_auto_join"]},"ssoSetupPending":{"type":"boolean","readOnly":true,"description":"When true, the user must complete SSO setup for this account\nbefore their SSO-required access is fully active. Set by the\nserver during SSO enrollment; cleared by removing the field, so\nit is never `false`."},"sharedWithUser":{"type":"object","readOnly":true,"description":"Identity details of the invited/shared user. Present on the list and\ninvite responses; `GET /v1/ashares/{_id}` returns `_sharedWithUserId`\nin its place.","properties":{"_id":{"type":"string","format":"objectId","description":"The user's own account id."},"email":{"type":"string","format":"email","description":"Email address of the user."},"name":{"type":"string","description":"Display name of the user."},"lastSignIn":{"type":"string","format":"date-time","description":"When the user last signed in (across any account)."},"allowedToResetMFA":{"type":"boolean","description":"When true, the current requester can reset MFA for this user."},"accountSSOLinked":{"type":"string","description":"SSO linkage status for the user in this account.\n`this_account` means SSO is linked to the current account.\n`other_account` means SSO is linked to a different account.","enum":["not_linked","this_account","other_account"]}}}}},{"$ref":"#/components/schemas/ResourceResponse"}]},"UserBase":{"type":"object","description":"Writable fields shared by the request and response schemas.","properties":{"accessLevel":{"type":"string","description":"Account-level access for the user.\n\n**CRITICAL**: This controls account-wide access. Choose your strategy:\n\n- Integration-only access: omit `accessLevel` and specify integrations in `integrationAccessLevel`\n- Account-wide monitoring + selective management: set `accessLevel: monitor` and use `integrationAccessLevel`\n  to grant `manage` access for specific integrations\n- Full account access: set `accessLevel: manage` or `accessLevel: administrator` and leave\n  `integrationAccessLevel` undefined/empty\n\nIf per-integration level permissions are needed, omit `accessLevel` and instead populate `integrationAccessLevel`.\n\nOn update (`PUT /v1/ashares/{_id}`) the body replaces the access settings: `integrationAccessLevel`\nand `accountMFARequired` are cleared when omitted, so resend them to keep them. `accountSSORequired`\nis different — it changes only when the body carries it.\n\n`none` is written by SCIM provisioning for a user who has no account-wide grant; do not send it\nyourself — omit `accessLevel` and use `integrationAccessLevel` for integration-only access.","enum":["monitor","manage","administrator","none"]},"integrationAccessLevel":{"type":"array","description":"Per-integration access levels for the user.\n\nUse this for granting access to specific integrations.\n\n- If `accessLevel` is omitted, this creates **integration-only** access.\n- If `accessLevel` is `monitor`, this grants **elevated access** (typically `manage`) for specific integrations.\n- If `accessLevel` is `manage` or `administrator`, do not set `integrationAccessLevel`.\n\nCleared when omitted on update — send `[]` explicitly only when you mean no per-integration grants.","items":{"type":"object","properties":{"_integrationId":{"type":"string","format":"objectId","description":"Integration ID the user should have access to."},"accessLevel":{"type":"string","description":"Access level for this integration.","enum":["monitor","manage"]}}}},"accountSSORequired":{"type":"boolean","description":"When true, the user must sign in through SSO to access this account. Written\nonly when present in the update body — omitting it on `PUT /v1/ashares/{_id}`\nleaves the stored value unchanged. While the account enforces SSO for every\nuser, the value sent is ignored and the stored value is kept until that\nenforcement is turned off."},"accountMFARequired":{"type":"boolean","description":"When true, MFA is required for this user in this account. Cleared when\nomitted on update — resend it with every `PUT /v1/ashares/{_id}`."},"allowAccessToAPIM":{"type":"boolean","description":"When true, the user can access API Management (APIM) features for this account."},"allowToEditRetryData":{"type":"boolean","description":"When true, the user can edit retry data when troubleshooting flow run errors (Error Management).\n\nAll users with **Monitor** access can view, retry, and resolve errant records. This flag controls whether they\ncan also **edit the retry data payload**. If set to false, the user cannot edit retry data for flow runs in any\nintegration workspace where they only have **Monitor** access.\n\nThis setting only applies when:\n- `accessLevel` is `monitor`, or\n- an entry in `integrationAccessLevel` grants `monitor` access for a specific integration."},"allowIntegrationWorkspaceCreation":{"type":"boolean","description":"When true, the user can create integration workspaces."}}},"ResourceResponse":{"type":"object","description":"Response","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource. Format is a 24-character hexadecimal string."},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was created. Set automatically and cannot be modified."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was last updated. Changes whenever any property is modified."},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp when the resource was soft-deleted. When null or absent, the resource is active."}},"required":["_id"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/ashares/{_id}":{"get":{"summary":"Get a user","operationId":"getUser","tags":["Users"],"description":"Retrieve a single user's access record by its id. Returns the bare record:\nthe user is identified by `_sharedWithUserId` rather than the expanded\n`sharedWithUser` the list returns, and `isProductionAdmin` is not computed.\nReturns workspace records only — an end-user access-record id is not found\nhere; read those from `GET /v1/endusers`.","parameters":[{"name":"_id","in":"path","required":true,"description":"User access-record id.","schema":{"type":"string","format":"objectId"}}],"responses":{"200":{"description":"The user record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Update a user

> Replaces a workspace user's access settings. The body must grant access\
> through \`accessLevel\` or a non-empty \`integrationAccessLevel\`, and\
> \`integrationAccessLevel\` and \`accountMFARequired\` are cleared when\
> omitted — send every value to keep. \`accountSSORequired\` is the\
> exception: it changes only when the body carries it, and is ignored\
> while the account enforces SSO for every user. \`disabled\` is not\
> applied here; toggle it with \`PUT /v1/ashares/{\_userId}/disable\`.\
> Read-only fields echoed from the GET response are ignored, except\
> \`userType\`, which is rejected. The user's email cannot be changed after\
> invite. Callable from the production environment only.\
> \
> End-user access records share this route with a different body — see\
> the End Users API.

```json
{"openapi":"3.2.0","info":{"title":"Users","version":"1.0.0"},"tags":[{"name":"Users","description":"Manage user access to a Celigo account. Each record represents a user's\naccess grant, including their access level and invitation status.\n\nAccess is controlled at two levels:\n- **accessLevel** — account-wide role (administrator, manage, monitor, etc.)\n- **integrationAccessLevel** — per-integration overrides for finer control.\n\nThe account owner is not included — only invited users appear. Users can\nbe disabled (reversible) or permanently removed.\n\n## User schema\n\n{% openapi-schemas spec=\"user\" schemas=\"User\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"Request":{"type":"object","description":"Fields that can be sent when inviting or updating an account user.","allOf":[{"$ref":"#/components/schemas/UserBase"}]},"UserBase":{"type":"object","description":"Writable fields shared by the request and response schemas.","properties":{"accessLevel":{"type":"string","description":"Account-level access for the user.\n\n**CRITICAL**: This controls account-wide access. Choose your strategy:\n\n- Integration-only access: omit `accessLevel` and specify integrations in `integrationAccessLevel`\n- Account-wide monitoring + selective management: set `accessLevel: monitor` and use `integrationAccessLevel`\n  to grant `manage` access for specific integrations\n- Full account access: set `accessLevel: manage` or `accessLevel: administrator` and leave\n  `integrationAccessLevel` undefined/empty\n\nIf per-integration level permissions are needed, omit `accessLevel` and instead populate `integrationAccessLevel`.\n\nOn update (`PUT /v1/ashares/{_id}`) the body replaces the access settings: `integrationAccessLevel`\nand `accountMFARequired` are cleared when omitted, so resend them to keep them. `accountSSORequired`\nis different — it changes only when the body carries it.\n\n`none` is written by SCIM provisioning for a user who has no account-wide grant; do not send it\nyourself — omit `accessLevel` and use `integrationAccessLevel` for integration-only access.","enum":["monitor","manage","administrator","none"]},"integrationAccessLevel":{"type":"array","description":"Per-integration access levels for the user.\n\nUse this for granting access to specific integrations.\n\n- If `accessLevel` is omitted, this creates **integration-only** access.\n- If `accessLevel` is `monitor`, this grants **elevated access** (typically `manage`) for specific integrations.\n- If `accessLevel` is `manage` or `administrator`, do not set `integrationAccessLevel`.\n\nCleared when omitted on update — send `[]` explicitly only when you mean no per-integration grants.","items":{"type":"object","properties":{"_integrationId":{"type":"string","format":"objectId","description":"Integration ID the user should have access to."},"accessLevel":{"type":"string","description":"Access level for this integration.","enum":["monitor","manage"]}}}},"accountSSORequired":{"type":"boolean","description":"When true, the user must sign in through SSO to access this account. Written\nonly when present in the update body — omitting it on `PUT /v1/ashares/{_id}`\nleaves the stored value unchanged. While the account enforces SSO for every\nuser, the value sent is ignored and the stored value is kept until that\nenforcement is turned off."},"accountMFARequired":{"type":"boolean","description":"When true, MFA is required for this user in this account. Cleared when\nomitted on update — resend it with every `PUT /v1/ashares/{_id}`."},"allowAccessToAPIM":{"type":"boolean","description":"When true, the user can access API Management (APIM) features for this account."},"allowToEditRetryData":{"type":"boolean","description":"When true, the user can edit retry data when troubleshooting flow run errors (Error Management).\n\nAll users with **Monitor** access can view, retry, and resolve errant records. This flag controls whether they\ncan also **edit the retry data payload**. If set to false, the user cannot edit retry data for flow runs in any\nintegration workspace where they only have **Monitor** access.\n\nThis setting only applies when:\n- `accessLevel` is `monitor`, or\n- an entry in `integrationAccessLevel` grants `monitor` access for a specific integration."},"allowIntegrationWorkspaceCreation":{"type":"boolean","description":"When true, the user can create integration workspaces."}}},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/ashares/{_id}":{"put":{"summary":"Update a user","operationId":"updateUser","tags":["Users"],"description":"Replaces a workspace user's access settings. The body must grant access\nthrough `accessLevel` or a non-empty `integrationAccessLevel`, and\n`integrationAccessLevel` and `accountMFARequired` are cleared when\nomitted — send every value to keep. `accountSSORequired` is the\nexception: it changes only when the body carries it, and is ignored\nwhile the account enforces SSO for every user. `disabled` is not\napplied here; toggle it with `PUT /v1/ashares/{_userId}/disable`.\nRead-only fields echoed from the GET response are ignored, except\n`userType`, which is rejected. The user's email cannot be changed after\ninvite. Callable from the production environment only.\n\nEnd-user access records share this route with a different body — see\nthe End Users API.","parameters":[{"name":"_id","in":"path","required":true,"description":"User access-record id.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Request"}}}},"responses":{"204":{"description":"User updated."},"400":{"description":"The body grants no access, or echoes the read-only `userType`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"403":{"description":"The call was made from a sandbox environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"$ref":"#/components/responses/404-not-found"},"422":{"description":"`integrationAccessLevel` is empty and no `accessLevel` was sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```

## Delete a user

> Remove a user from the current account. This is irreversible — for a\
> reversible alternative, use \`PUT /v1/ashares/{\_id}/disable\`. Works\
> on both accepted and pending invites.

```json
{"openapi":"3.2.0","info":{"title":"Users","version":"1.0.0"},"tags":[{"name":"Users","description":"Manage user access to a Celigo account. Each record represents a user's\naccess grant, including their access level and invitation status.\n\nAccess is controlled at two levels:\n- **accessLevel** — account-wide role (administrator, manage, monitor, etc.)\n- **integrationAccessLevel** — per-integration overrides for finer control.\n\nThe account owner is not included — only invited users appear. Users can\nbe disabled (reversible) or permanently removed.\n\n## User schema\n\n{% openapi-schemas spec=\"user\" schemas=\"User\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}}},"paths":{"/v1/ashares/{_id}":{"delete":{"summary":"Delete a user","operationId":"deleteUser","tags":["Users"],"description":"Remove a user from the current account. This is irreversible — for a\nreversible alternative, use `PUT /v1/ashares/{_id}/disable`. Works\non both accepted and pending invites.","parameters":[{"name":"_id","in":"path","required":true,"description":"User access-record id.","schema":{"type":"string","format":"objectId"}}],"responses":{"204":{"description":"User removed from the account."},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Toggle a user's account access (disable or re-enable)

> Toggles the \`disabled\` flag on a user's access record. Call again to\
> re-enable — there is no separate \`/enable\` path, and this is the only\
> way to change \`disabled\` (the update operation does not apply it). A\
> pending invitation cannot be toggled until the invited user accepts or\
> declines it.\
> \
> End-user access records share this route — see the End Users API.

```json
{"openapi":"3.2.0","info":{"title":"Users","version":"1.0.0"},"tags":[{"name":"Users","description":"Manage user access to a Celigo account. Each record represents a user's\naccess grant, including their access level and invitation status.\n\nAccess is controlled at two levels:\n- **accessLevel** — account-wide role (administrator, manage, monitor, etc.)\n- **integrationAccessLevel** — per-integration overrides for finer control.\n\nThe account owner is not included — only invited users appear. Users can\nbe disabled (reversible) or permanently removed.\n\n## User schema\n\n{% openapi-schemas spec=\"user\" schemas=\"User\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/ashares/{_userId}/disable":{"put":{"operationId":"toggleUserDisabled","tags":["Users"],"summary":"Toggle a user's account access (disable or re-enable)","description":"Toggles the `disabled` flag on a user's access record. Call again to\nre-enable — there is no separate `/enable` path, and this is the only\nway to change `disabled` (the update operation does not apply it). A\npending invitation cannot be toggled until the invited user accepts or\ndeclines it.\n\nEnd-user access records share this route — see the End Users API.","parameters":[{"name":"_userId","in":"path","required":true,"description":"The ashare record `_id` from `GET /v1/ashares` — despite the\nparameter name, this is NOT `sharedWithUser._id`.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","description":"Empty body — the target is identified by the path parameter alone."}}}},"responses":{"204":{"description":"User access toggled."},"400":{"description":"The invitation is still pending.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"description":"User not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```

## Reinvite a user who dismissed their invite

> Re-sends the invitation to a user who previously dismissed it. Only\
> works on users with \`dismissed: true\` in the user record. After\
> reinviting, the user returns to a pending state awaiting acceptance.

```json
{"openapi":"3.2.0","info":{"title":"Users","version":"1.0.0"},"tags":[{"name":"Users","description":"Manage user access to a Celigo account. Each record represents a user's\naccess grant, including their access level and invitation status.\n\nAccess is controlled at two levels:\n- **accessLevel** — account-wide role (administrator, manage, monitor, etc.)\n- **integrationAccessLevel** — per-integration overrides for finer control.\n\nThe account owner is not included — only invited users appear. Users can\nbe disabled (reversible) or permanently removed.\n\n## User schema\n\n{% openapi-schemas spec=\"user\" schemas=\"User\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/ashares/{_id}/reinvite":{"put":{"summary":"Reinvite a user who dismissed their invite","description":"Re-sends the invitation to a user who previously dismissed it. Only\nworks on users with `dismissed: true` in the user record. After\nreinviting, the user returns to a pending state awaiting acceptance.","operationId":"reinviteUser","tags":["Users"],"parameters":[{"name":"_id","in":"path","required":true,"description":"User access-record id.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","description":"Empty body."}}}},"responses":{"204":{"description":"Reinvitation sent."},"400":{"description":"User has not dismissed the invite.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Accept an account invitation

> Accepts an invitation to another user's account on behalf of the caller.\
> The \`\_id\` is a share record addressed \*to\* the caller — take it from\
> \`GET /v1/shared/ashares\`, not from \`GET /v1/ashares\`. Pending invitations\
> from the same owner's other environments are accepted with it, and the\
> owner is notified by email. Accepting an invitation that is already\
> accepted changes nothing. A user who still owns integrations, flows, or\
> syncs must transfer or delete them before they can join another account.

```json
{"openapi":"3.2.0","info":{"title":"Users","version":"1.0.0"},"tags":[{"name":"Users","description":"Manage user access to a Celigo account. Each record represents a user's\naccess grant, including their access level and invitation status.\n\nAccess is controlled at two levels:\n- **accessLevel** — account-wide role (administrator, manage, monitor, etc.)\n- **integrationAccessLevel** — per-integration overrides for finer control.\n\nThe account owner is not included — only invited users appear. Users can\nbe disabled (reversible) or permanently removed.\n\n## User schema\n\n{% openapi-schemas spec=\"user\" schemas=\"User\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}},"schemas":{"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}}},"paths":{"/v1/ashares/{_id}/accept":{"put":{"summary":"Accept an account invitation","operationId":"acceptAccountInvitation","tags":["Users"],"description":"Accepts an invitation to another user's account on behalf of the caller.\nThe `_id` is a share record addressed *to* the caller — take it from\n`GET /v1/shared/ashares`, not from `GET /v1/ashares`. Pending invitations\nfrom the same owner's other environments are accepted with it, and the\nowner is notified by email. Accepting an invitation that is already\naccepted changes nothing. A user who still owns integrations, flows, or\nsyncs must transfer or delete them before they can join another account.","parameters":[{"name":"_id","in":"path","required":true,"description":"Share record id from `GET /v1/shared/ashares`.","schema":{"type":"string","format":"objectId"}}],"responses":{"204":{"description":"Invitation accepted (or already accepted)."},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"description":"No share with this id is addressed to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```

## Dismiss an account invitation

> Declines an invitation to another user's account on behalf of the caller.\
> The \`\_id\` is a share record addressed \*to\* the caller — take it from\
> \`GET /v1/shared/ashares\`. Pending invitations from the same owner's other\
> environments are dismissed with it, and the owner is notified by email;\
> they can send it again with \`PUT /v1/ashares/{\_id}/reinvite\`. Dismissing\
> an invitation that is already dismissed changes nothing. To leave an\
> account whose invitation you accepted, use \`DELETE /v1/shared/ashares/{\_id}\`.

```json
{"openapi":"3.2.0","info":{"title":"Users","version":"1.0.0"},"tags":[{"name":"Users","description":"Manage user access to a Celigo account. Each record represents a user's\naccess grant, including their access level and invitation status.\n\nAccess is controlled at two levels:\n- **accessLevel** — account-wide role (administrator, manage, monitor, etc.)\n- **integrationAccessLevel** — per-integration overrides for finer control.\n\nThe account owner is not included — only invited users appear. Users can\nbe disabled (reversible) or permanently removed.\n\n## User schema\n\n{% openapi-schemas spec=\"user\" schemas=\"User\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}},"schemas":{"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}}},"paths":{"/v1/ashares/{_id}/dismiss":{"put":{"summary":"Dismiss an account invitation","operationId":"dismissAccountInvitation","tags":["Users"],"description":"Declines an invitation to another user's account on behalf of the caller.\nThe `_id` is a share record addressed *to* the caller — take it from\n`GET /v1/shared/ashares`. Pending invitations from the same owner's other\nenvironments are dismissed with it, and the owner is notified by email;\nthey can send it again with `PUT /v1/ashares/{_id}/reinvite`. Dismissing\nan invitation that is already dismissed changes nothing. To leave an\naccount whose invitation you accepted, use `DELETE /v1/shared/ashares/{_id}`.","parameters":[{"name":"_id","in":"path","required":true,"description":"Share record id from `GET /v1/shared/ashares`.","schema":{"type":"string","format":"objectId"}}],"responses":{"204":{"description":"Invitation dismissed (or already dismissed)."},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"description":"No share with this id is addressed to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```

## Invite users to the account

> Invite one or more users by email. Each entry in the response array\
> corresponds to the email at the same index — check \`statusCode\` per\
> entry for partial failures.

```json
{"openapi":"3.2.0","info":{"title":"Users","version":"1.0.0"},"tags":[{"name":"Users","description":"Manage user access to a Celigo account. Each record represents a user's\naccess grant, including their access level and invitation status.\n\nAccess is controlled at two levels:\n- **accessLevel** — account-wide role (administrator, manage, monitor, etc.)\n- **integrationAccessLevel** — per-integration overrides for finer control.\n\nThe account owner is not included — only invited users appear. Users can\nbe disabled (reversible) or permanently removed.\n\n## User schema\n\n{% openapi-schemas spec=\"user\" schemas=\"User\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"InviteRequest":{"description":"Request body for inviting users to the account. Extends the base\nuser request with email fields. Access settings apply uniformly\nto all emails in a batch invite.","allOf":[{"$ref":"#/components/schemas/Request"},{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Single email address to invite (use with `POST /v1/invite`)."},"emails":{"type":"array","description":"Email addresses to invite (use with `POST /v1/invite/multiple`).","items":{"type":"string","format":"email"}}}}]},"Request":{"type":"object","description":"Fields that can be sent when inviting or updating an account user.","allOf":[{"$ref":"#/components/schemas/UserBase"}]},"UserBase":{"type":"object","description":"Writable fields shared by the request and response schemas.","properties":{"accessLevel":{"type":"string","description":"Account-level access for the user.\n\n**CRITICAL**: This controls account-wide access. Choose your strategy:\n\n- Integration-only access: omit `accessLevel` and specify integrations in `integrationAccessLevel`\n- Account-wide monitoring + selective management: set `accessLevel: monitor` and use `integrationAccessLevel`\n  to grant `manage` access for specific integrations\n- Full account access: set `accessLevel: manage` or `accessLevel: administrator` and leave\n  `integrationAccessLevel` undefined/empty\n\nIf per-integration level permissions are needed, omit `accessLevel` and instead populate `integrationAccessLevel`.\n\nOn update (`PUT /v1/ashares/{_id}`) the body replaces the access settings: `integrationAccessLevel`\nand `accountMFARequired` are cleared when omitted, so resend them to keep them. `accountSSORequired`\nis different — it changes only when the body carries it.\n\n`none` is written by SCIM provisioning for a user who has no account-wide grant; do not send it\nyourself — omit `accessLevel` and use `integrationAccessLevel` for integration-only access.","enum":["monitor","manage","administrator","none"]},"integrationAccessLevel":{"type":"array","description":"Per-integration access levels for the user.\n\nUse this for granting access to specific integrations.\n\n- If `accessLevel` is omitted, this creates **integration-only** access.\n- If `accessLevel` is `monitor`, this grants **elevated access** (typically `manage`) for specific integrations.\n- If `accessLevel` is `manage` or `administrator`, do not set `integrationAccessLevel`.\n\nCleared when omitted on update — send `[]` explicitly only when you mean no per-integration grants.","items":{"type":"object","properties":{"_integrationId":{"type":"string","format":"objectId","description":"Integration ID the user should have access to."},"accessLevel":{"type":"string","description":"Access level for this integration.","enum":["monitor","manage"]}}}},"accountSSORequired":{"type":"boolean","description":"When true, the user must sign in through SSO to access this account. Written\nonly when present in the update body — omitting it on `PUT /v1/ashares/{_id}`\nleaves the stored value unchanged. While the account enforces SSO for every\nuser, the value sent is ignored and the stored value is kept until that\nenforcement is turned off."},"accountMFARequired":{"type":"boolean","description":"When true, MFA is required for this user in this account. Cleared when\nomitted on update — resend it with every `PUT /v1/ashares/{_id}`."},"allowAccessToAPIM":{"type":"boolean","description":"When true, the user can access API Management (APIM) features for this account."},"allowToEditRetryData":{"type":"boolean","description":"When true, the user can edit retry data when troubleshooting flow run errors (Error Management).\n\nAll users with **Monitor** access can view, retry, and resolve errant records. This flag controls whether they\ncan also **edit the retry data payload**. If set to false, the user cannot edit retry data for flow runs in any\nintegration workspace where they only have **Monitor** access.\n\nThis setting only applies when:\n- `accessLevel` is `monitor`, or\n- an entry in `integrationAccessLevel` grants `monitor` access for a specific integration."},"allowIntegrationWorkspaceCreation":{"type":"boolean","description":"When true, the user can create integration workspaces."}}},"User":{"type":"object","required":["_id","integrationAccessLevel","createdAt","lastModified"],"description":"A user's access record in the account. Each user who has been invited\n(or shared access) gets one record per account they belong to. The\n`_id` is the access-record id, not the user's own id — the user's\nidentity is in `sharedWithUser._id` on list and invite responses, and\nin `_sharedWithUserId` on `GET /v1/ashares/{_id}`. The account owner\ndoes not appear in this list.","allOf":[{"$ref":"#/components/schemas/UserBase"},{"type":"object","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Access-record id for this user in the account."},"_sharedWithUserId":{"type":"string","format":"objectId","readOnly":true,"description":"The user's own account id. Present on `GET /v1/ashares/{_id}`, which\nreturns the bare record; the list and invite responses expand it into\n`sharedWithUser` instead."},"accepted":{"type":"boolean","readOnly":true,"description":"When true, the user has accepted the invitation to join the account."},"disabled":{"type":"boolean","readOnly":true,"description":"When true, the user's access to the account is suspended. Changed\nonly by `PUT /v1/ashares/{_userId}/disable` — a value sent on the\nupdate operation is accepted but not applied."},"userType":{"type":"string","readOnly":true,"enum":["workspace"],"description":"Discriminates workspace users from end users on the underlying\naccess-record model. Reads on this API return only `workspace`\nrecords — end users are managed through the End Users API, which\nshares the update and disable routes. Sending it back on update\nis rejected."},"lastSignIn":{"type":"string","format":"date-time","readOnly":true,"description":"When the user last signed in to this account."},"dismissed":{"type":"boolean","readOnly":true,"description":"When true, the invitation has been declined by the user."},"isProductionAdmin":{"type":"boolean","readOnly":true,"description":"When true, the user has production-admin privileges in this account."},"createdVia":{"type":"string","readOnly":true,"description":"How this user's access record was created.","enum":["existing_account_invite","existing_account_share_request","invited_during_signup","new_account_auto_join"]},"ssoSetupPending":{"type":"boolean","readOnly":true,"description":"When true, the user must complete SSO setup for this account\nbefore their SSO-required access is fully active. Set by the\nserver during SSO enrollment; cleared by removing the field, so\nit is never `false`."},"sharedWithUser":{"type":"object","readOnly":true,"description":"Identity details of the invited/shared user. Present on the list and\ninvite responses; `GET /v1/ashares/{_id}` returns `_sharedWithUserId`\nin its place.","properties":{"_id":{"type":"string","format":"objectId","description":"The user's own account id."},"email":{"type":"string","format":"email","description":"Email address of the user."},"name":{"type":"string","description":"Display name of the user."},"lastSignIn":{"type":"string","format":"date-time","description":"When the user last signed in (across any account)."},"allowedToResetMFA":{"type":"boolean","description":"When true, the current requester can reset MFA for this user."},"accountSSOLinked":{"type":"string","description":"SSO linkage status for the user in this account.\n`this_account` means SSO is linked to the current account.\n`other_account` means SSO is linked to a different account.","enum":["not_linked","this_account","other_account"]}}}}},{"$ref":"#/components/schemas/ResourceResponse"}]},"ResourceResponse":{"type":"object","description":"Response","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource. Format is a 24-character hexadecimal string."},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was created. Set automatically and cannot be modified."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was last updated. Changes whenever any property is modified."},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp when the resource was soft-deleted. When null or absent, the resource is active."}},"required":["_id"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/invite/multiple":{"post":{"summary":"Invite users to the account","description":"Invite one or more users by email. Each entry in the response array\ncorresponds to the email at the same index — check `statusCode` per\nentry for partial failures.","operationId":"inviteUsers","tags":["Users"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteRequest"}}}},"responses":{"200":{"description":"Array of results, one per email.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"statusCode":{"type":"integer","description":"Per-entry result code. `201` on success, `400` if\nthe user already has access (use `PUT /v1/ashares/{_id}`\nto update permissions instead)."},"doc":{"$ref":"#/components/schemas/User"}}}}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"}}}}}}
```
