App installations tools
MCP tools for App installations: app_installations_activity, app_installations_create, app_installations_create_agent, app_installations_get, app_installations_list, app_installations_pause, app_installations_reassign, app_installations_resume, app_installations_revoke, app_installations_update.
app_installations_activity: List an installed app's activityapp_installations_create: Install an app (consent)app_installations_create_agent: Ask for an agent the app ownsapp_installations_get: Get an installed appapp_installations_list: List installed appsapp_installations_pause: Pause an installed appapp_installations_reassign: Re-assign an installed appapp_installations_resume: Resume a paused appapp_installations_revoke: Uninstall an appapp_installations_update: Narrow an installed app's access
app_installations_activity
List an installed app's activity. Operation app_installations.activity · Organization level · permission audit:read · risk tier read · since M10
The installed app's activity feed in this organization, newest first, from the audit log: every change it made
(outcome: "succeeded"), every call that asked for approval instead of running (approval_requested, with the
approval's current status), and every run a person approved (ran_after_approval), each with the operation,
its target, the mode, the entity or brand, the surface (via), the app's OAuth client and the installer the
call was attributed to (onBehalfOfUserId). Reads aren't in the audit log, so they aren't listed. Both modes
are listed; usage is today's use (UTC) of its daily limits in the request's mode. Paginate with limit
(1–100, default 10) and starting_after.
Annotations: readOnlyHint: true · destructiveHint: false · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID (ains_…) | yes | – |
limit | integer | no | (1–100) |
starting_after | ID (aud_…) | no | – |
- Read-only: changes nothing;
idempotency_keyis ignored.
Errors
validation_failed:limitorstarting_afteris invalid.resource_not_found: No installation with this ID exists in the organization.permission_denied: You can't read the organization's audit log.
Example
A refund above the daily limit, approved and run
Arguments:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc"
}
Result output:
{
"object": "list",
"data": [
{
"object": "activity_entry",
"livemode": false,
"entityId": "ent_01m4ttwd3veh9apbewxheq5xh4",
"brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
"via": "mcp",
"clientId": "ocl_01m4ttwd3veh9apbewxheq5xha",
"onBehalfOfUserId": "usr_01m4ttwd3veh9apbewxheq5xh6",
"appInstallationId": null,
"id": "aud_01m4ttwd3veh9apbewxheq5xhh",
"at": "2026-10-26T15:02:11.000Z",
"action": "refunds.create",
"operationId": "refunds.create",
"target": "re_01m4ttwd3veh9apbewxheq5xhj",
"outcome": "ran_after_approval",
"approval": {
"id": "apr_01m4ttwd3veh9apbewxheq5xhk",
"status": "executed",
"approvedBy": ["usr_01m4ttwd3veh9apbewxheq5xh7"]
}
},
{
"object": "activity_entry",
"livemode": false,
"entityId": "ent_01m4ttwd3veh9apbewxheq5xh4",
"brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
"via": "mcp",
"clientId": "ocl_01m4ttwd3veh9apbewxheq5xha",
"onBehalfOfUserId": "usr_01m4ttwd3veh9apbewxheq5xh6",
"appInstallationId": null,
"id": "aud_01m4ttwd3veh9apbewxheq5xhf",
"at": "2026-10-26T14:30:00.000Z",
"action": "approvals.request",
"operationId": "refunds.create",
"target": "apr_01m4ttwd3veh9apbewxheq5xhk",
"outcome": "approval_requested",
"approval": {
"id": "apr_01m4ttwd3veh9apbewxheq5xhk",
"status": "executed",
"approvedBy": ["usr_01m4ttwd3veh9apbewxheq5xh7"]
}
},
{
"object": "activity_entry",
"livemode": false,
"entityId": "ent_01m4ttwd3veh9apbewxheq5xh4",
"brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
"via": "mcp",
"clientId": "ocl_01m4ttwd3veh9apbewxheq5xha",
"onBehalfOfUserId": "usr_01m4ttwd3veh9apbewxheq5xh6",
"appInstallationId": null,
"id": "aud_01m4ttwd3veh9apbewxheq5xhg",
"at": "2026-10-26T14:10:00.000Z",
"action": "refunds.create",
"operationId": "refunds.create",
"target": "re_01m4ttwd3veh9apbewxheq5xhm",
"outcome": "succeeded",
"approval": null
}
],
"has_more": false,
"next_cursor": null,
"usage": {
"day": "2026-10-26",
"livemode": false,
"mutations": 2,
"amounts": [
{
"operationId": "refunds.create",
"amount": {
"amount": "450000000",
"currency": "EUR"
}
}
]
}
}
app_installations_create
Install an app (consent). Operation app_installations.create · Organization level · permission agents:admin · risk tier security · since M10
Installs a partner app in the organization with the scopes you consent to, optionally limited to some legal
entities or brands (limitTo; none = the whole organization). The consent screen calls it when an
organization owner or admin approves an app's authorization request; grantId is that request's grant.
The app then acts in the organization as the installation, attributed to you, with at most your own access,
re-checked on every call. By installing it, the organization instructs Ownrecord to disclose the data in these
scopes to the app's publisher. Installing an app that is already installed updates its scopes and limitTo
and makes you its installer. Private apps install only in the organization that registered them.
Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
clientId | ID (ocl_…) | yes | – |
grantId | ID (ogr_…) | yes | – |
scopes | array of one of 84 values, e.g. org:read, org:write, org:admin | yes | (1–200 items) |
limitTo | object | no | – |
idempotency_key | string | no | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters) |
dry_run | boolean | no | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false) |
- Idempotency: the result returns the
idempotency_keyused, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours). - Dry run: supported.
dry_run: truechecks permissions and rules and computes the result, then rolls everything back.
Errors
validation_failed: A scope isn't one the app registered, or a field is invalid.app_not_installable: The app is private to another organization, or listed but not (yet) approved in platform review.app_scopes_not_approved: Another organization's listed app: a scope its approved listing doesn't cover (it waits for re-review).oauth_client_disabled: The app is disabled.app_suspended: Ownrecord suspended the app: nothing installs it while the suspension lasts.oauth_grant_mismatch: The grant isn't yours or isn't the app's.resource_not_found: The app, or an entity or brand in limitTo, doesn't exist.permission_denied: You can't install apps, or this isn't a signed-in person.
Example
Install for one legal entity
Arguments:
{
"clientId": "ocl_01m4ttwd3veh9apbewxheq5xha",
"grantId": "ogr_01m4ttwd3veh9apbewxheq5xhd",
"scopes": ["filings:read", "filings:write", "tasks:read", "tasks:write"],
"limitTo": {
"entityIds": ["ent_01m4ttwd3veh9apbewxheq5xh4"]
},
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"object": "app_installation",
"orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
"app": {
"id": "ocl_01m4ttwd3veh9apbewxheq5xha",
"name": "Ledgerly AI",
"publisher": "Ledgerly AI B.V.",
"logoUrl": null,
"verified": true,
"status": "active",
"suspension": null
},
"installedBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
"scopes": ["filings:read", "filings:write", "tasks:read", "tasks:write"],
"limitTo": {
"entityIds": ["ent_01m4ttwd3veh9apbewxheq5xh4"],
"brandIds": []
},
"limits": {
"rps": null,
"mutationsPerDay": null,
"amountLimits": []
},
"status": "active",
"pausedReason": null,
"pausedAt": null,
"revokedAt": null,
"createdAt": "2026-10-25T09:00:00.000Z",
"updatedAt": "2026-10-25T09:00:00.000Z"
}
app_installations_create_agent
Ask for an agent the app owns. Operation app_installations.create_agent · Organization level · permission agents:admin · risk tier security · since M13
Called by an installed app with its own access token: asks for an agent the app owns in the organization,
for work that runs without the app's user session (for example a filing agent). It is a security operation, so
the call always answers 202 with an approval request: an owner or admin of the organization (not the person
who installed the app) approves it in the console, and the approved run creates the agent exactly as asked.
Poll the approval (approvals.get) or watch approval.resolved; its resultRef is the new agent's ID, and
agents.get returns its clientId.
The agent holds one role at a scope like a member, works in test mode unless livemodeAccess is asked for
and the installer may use live mode, and its token scopes stay within the scopes the app was granted (default:
everything the role can use among them). It authenticates with private_key_jwt only: give its public keys in
jwks. Its calls are attributed to the agent, the app's installation and the person who installed the app; it
stops when the app is paused or uninstalled, or the installer leaves the organization. id is your own
installation (ains_…); an installation limited to some entities or brands can't ask for agents.
Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: false · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID (ains_…) | yes | The calling app's installation in this organization. |
name | string | yes | (1–100 characters) |
description | string | no | (1–500 characters) |
contact | string | no | Who to contact about the agent (default: none). (1–500 characters) |
vendor | string | no | Model or vendor description (default: the app's publisher). (1–500 characters) |
role | one of org_admin, billing_admin, finance, tax_manager, support, developer, viewer | yes | – |
scope | object or object or object | no | (default {"type":"org"}) |
livemodeAccess | boolean | no | (default false) |
scopes | array of one of 84 values, e.g. org:read, org:write, org:admin | no | (1–200 items) |
jwks | object | yes | The agent's public keys for private_key_jwt client authentication. |
limits | object | no | – |
toolSets | array of string | no | (at most 20 items) |
idempotency_key | string | no | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters) |
dry_run | boolean | no | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false) |
- Idempotency: the result returns the
idempotency_keyused, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours). - Dry run: supported.
dry_run: truechecks permissions and rules and computes the result, then rolls everything back.
Errors
approval_required: Always for the app's own call: an owner or admin approves it in the console.validation_failed: A field is invalid, e.g. a scope the app wasn't granted or the role can't use.agent_role_invalid: The role is org_owner, or isn't allowed at the scope's type.agent_delegation_not_allowed: The agent would get a permission (or live access) the app doesn't have at its scope.resource_not_found: The installation isn't the calling app's, or the scope's entity or brand doesn't exist.app_installation_paused: The installation was paused before the approved run.oauth_client_disabled: The app was disabled before the approved run.permission_denied: The caller isn't an installed app (people create agents with agents.create), or lacks agents:admin.
Example
A filing agent for the whole organization (after approval)
Arguments:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"name": "Ledgerly Filing Agent",
"description": "Prepares and files the quarterly returns",
"contact": "filings@ledgerly.example",
"role": "finance",
"scopes": ["filings:read", "filings:write", "tasks:read", "tasks:write"],
"jwks": {
"keys": [
{
"kty": "EC",
"crv": "P-256",
"kid": "ledgerly-filing-1",
"x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
"y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"
}
]
},
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"agent": {
"id": "agt_01m4ttwd3veh9apbewxheq5xh8",
"object": "agent",
"orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
"name": "Ledgerly Filing Agent",
"description": "Prepares and files the quarterly returns",
"contact": "filings@ledgerly.example",
"vendor": "Ledgerly AI B.V.",
"ownerType": "app",
"appInstallationId": "ains_01m4ttwd3veh9apbewxheq5xhc",
"role": "finance",
"scope": {
"type": "org"
},
"livemodeAccess": false,
"limits": {
"rps": null,
"mutationsPerDay": null,
"amountLimits": []
},
"toolSets": [],
"status": "active",
"clientId": "ocl_01m4ttwd3veh9apbewxheq5xh9",
"authMethod": "private_key_jwt",
"secretPrefix": null,
"dpopBoundAccessTokens": false,
"scopes": ["filings:read", "filings:write", "tasks:read", "tasks:write"],
"createdBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
"createdAt": "2026-10-25T09:00:00.000Z",
"updatedAt": "2026-10-25T09:00:00.000Z",
"pausedAt": null,
"revokedAt": null
},
"credentials": {
"clientId": "ocl_01m4ttwd3veh9apbewxheq5xh9",
"clientSecret": null,
"tokenEndpoint": "https://ownrecord.io/oauth/token",
"authMethod": "private_key_jwt"
}
}
app_installations_get
Get an installed app. Operation app_installations.get · Organization level · permission agents:read · risk tier read · since M10
Returns one app installation of the organization: the app, the installer, scopes, limitTo and status.
Annotations: readOnlyHint: true · destructiveHint: false · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID (ains_…) | yes | – |
- Read-only: changes nothing;
idempotency_keyis ignored.
Errors
resource_not_found: No installation with this ID exists in the organization.permission_denied: You can't see the organization's agents and apps.
Example
An installation
Arguments:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc"
}
Result output:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"object": "app_installation",
"orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
"app": {
"id": "ocl_01m4ttwd3veh9apbewxheq5xha",
"name": "Ledgerly AI",
"publisher": "Ledgerly AI B.V.",
"logoUrl": null,
"verified": true,
"status": "active",
"suspension": null
},
"installedBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
"scopes": ["filings:read", "filings:write", "tasks:read", "tasks:write"],
"limitTo": {
"entityIds": ["ent_01m4ttwd3veh9apbewxheq5xh4"],
"brandIds": []
},
"limits": {
"rps": null,
"mutationsPerDay": null,
"amountLimits": []
},
"status": "active",
"pausedReason": null,
"pausedAt": null,
"revokedAt": null,
"createdAt": "2026-10-25T09:00:00.000Z",
"updatedAt": "2026-10-25T09:00:00.000Z"
}
app_installations_list
List installed apps. Operation app_installations.list · Organization level · permission agents:read · risk tier read · since M10
Lists the apps installed in the organization, newest first: the app and its publisher (verified or not), who installed it, the scopes granted, limitTo and the status. Filter by status; paginate with limit and starting_after.
Annotations: readOnlyHint: true · destructiveHint: false · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
limit | integer | no | (1–100) |
starting_after | ID (ains_…) | no | – |
status | one of active, paused, revoked | no | – |
- Read-only: changes nothing;
idempotency_keyis ignored.
Errors
validation_failed: A filter or pagination value is invalid.permission_denied: You can't see the organization's agents and apps.
Examples
Installed apps
Arguments:
{}
Result output:
{
"object": "list",
"data": [
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"object": "app_installation",
"orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
"app": {
"id": "ocl_01m4ttwd3veh9apbewxheq5xha",
"name": "Ledgerly AI",
"publisher": "Ledgerly AI B.V.",
"logoUrl": null,
"verified": true,
"status": "active",
"suspension": null
},
"installedBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
"scopes": ["filings:read", "filings:write", "tasks:read", "tasks:write"],
"limitTo": {
"entityIds": ["ent_01m4ttwd3veh9apbewxheq5xh4"],
"brandIds": []
},
"limits": {
"rps": null,
"mutationsPerDay": null,
"amountLimits": []
},
"status": "active",
"pausedReason": null,
"pausedAt": null,
"revokedAt": null,
"createdAt": "2026-10-25T09:00:00.000Z",
"updatedAt": "2026-10-25T09:00:00.000Z"
}
],
"has_more": false,
"next_cursor": null
}
Paused installations, one per page
Arguments:
{
"status": "paused",
"limit": 1
}
Result output:
{
"object": "list",
"data": [
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"object": "app_installation",
"orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
"app": {
"id": "ocl_01m4ttwd3veh9apbewxheq5xha",
"name": "Ledgerly AI",
"publisher": "Ledgerly AI B.V.",
"logoUrl": null,
"verified": true,
"status": "active",
"suspension": null
},
"installedBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
"scopes": ["filings:read", "filings:write", "tasks:read", "tasks:write"],
"limitTo": {
"entityIds": ["ent_01m4ttwd3veh9apbewxheq5xh4"],
"brandIds": []
},
"limits": {
"rps": null,
"mutationsPerDay": null,
"amountLimits": []
},
"status": "paused",
"pausedReason": "installer_lost_access",
"pausedAt": "2026-10-26T14:30:00.000Z",
"revokedAt": null,
"createdAt": "2026-10-25T09:00:00.000Z",
"updatedAt": "2026-10-26T14:30:00.000Z"
}
],
"has_more": true,
"next_cursor": "ains_01m4ttwd3veh9apbewxheq5xhc"
}
app_installations_pause
Pause an installed app. Operation app_installations.pause · Organization level · permission agents:admin · risk tier security · since M10
Pauses an installed app: its access tokens and refresh tokens stop working in the organization at once,
and it can't act there until resumed (app_installations.resume), after which it must ask for authorization
again. Pausing a paused app changes nothing (one paused because its installer left stays so, keeping its
tokens for after the re-assignment).
Annotations: readOnlyHint: false · destructiveHint: true · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID (ains_…) | yes | – |
idempotency_key | string | no | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters) |
dry_run | boolean | no | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false) |
- Idempotency: the result returns the
idempotency_keyused, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours). - Dry run: supported.
dry_run: truechecks permissions and rules and computes the result, then rolls everything back.
Errors
validation_failed: The installation is revoked.resource_not_found: No installation with this ID exists in the organization.version_conflict: The installation changed at the same moment; retry.permission_denied: You can't manage the organization's apps.
Example
Pause an app
Arguments:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"object": "app_installation",
"orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
"app": {
"id": "ocl_01m4ttwd3veh9apbewxheq5xha",
"name": "Ledgerly AI",
"publisher": "Ledgerly AI B.V.",
"logoUrl": null,
"verified": true,
"status": "active",
"suspension": null
},
"installedBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
"scopes": ["filings:read", "filings:write", "tasks:read", "tasks:write"],
"limitTo": {
"entityIds": ["ent_01m4ttwd3veh9apbewxheq5xh4"],
"brandIds": []
},
"limits": {
"rps": null,
"mutationsPerDay": null,
"amountLimits": []
},
"status": "paused",
"pausedReason": "manual",
"pausedAt": "2026-10-26T14:30:00.000Z",
"revokedAt": null,
"createdAt": "2026-10-25T09:00:00.000Z",
"updatedAt": "2026-10-26T14:30:00.000Z"
}
app_installations_reassign
Re-assign an installed app. Operation app_installations.reassign · Organization level · permission agents:admin · risk tier security · since M10
Makes another organization owner or admin the installer of an app: its calls are attributed to them and limited
to their access from now on. An installation paused because its installer left resumes, with the same tokens.
The new installer must be an org_owner or org_admin of the organization.
Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID (ains_…) | yes | – |
userId | ID (usr_…) | yes | – |
idempotency_key | string | no | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters) |
dry_run | boolean | no | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false) |
- Idempotency: the result returns the
idempotency_keyused, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours). - Dry run: supported.
dry_run: truechecks permissions and rules and computes the result, then rolls everything back.
Errors
validation_failed: The installation is revoked.installer_not_eligible: The person isn't an active org_owner or org_admin of the organization.resource_not_found: No installation with this ID exists in the organization.version_conflict: The installation changed at the same moment; retry.permission_denied: You can't manage the organization's apps.
Example
Re-assign after the installer left
Arguments:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"userId": "usr_01m4ttwd3veh9apbewxheq5xh7",
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"object": "app_installation",
"orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
"app": {
"id": "ocl_01m4ttwd3veh9apbewxheq5xha",
"name": "Ledgerly AI",
"publisher": "Ledgerly AI B.V.",
"logoUrl": null,
"verified": true,
"status": "active",
"suspension": null
},
"installedBy": "usr_01m4ttwd3veh9apbewxheq5xh7",
"scopes": ["filings:read", "filings:write", "tasks:read", "tasks:write"],
"limitTo": {
"entityIds": ["ent_01m4ttwd3veh9apbewxheq5xh4"],
"brandIds": []
},
"limits": {
"rps": null,
"mutationsPerDay": null,
"amountLimits": []
},
"status": "active",
"pausedReason": null,
"pausedAt": null,
"revokedAt": null,
"createdAt": "2026-10-25T09:00:00.000Z",
"updatedAt": "2026-10-26T14:30:00.000Z"
}
app_installations_resume
Resume a paused app. Operation app_installations.resume · Organization level · permission agents:admin · risk tier security · since M10
Resumes a paused installation. After a manual pause the app must ask for authorization again (its tokens
were revoked). An installation paused because its installer left can only resume once its installer has access
again: re-assign it instead (app_installations.reassign), which also resumes it. Resuming an active
installation changes nothing; a revoked one can't be resumed.
While Ownrecord suspends the app (pausedReason: platform_suspended), it can't be resumed (app_suspended).
After a reinstatement, resuming it is your decision; the app then asks for authorization again.
An app disabled by the organization that registered it (pausedReason: app_disabled) never resumes
(oauth_client_disabled): uninstall it.
Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID (ains_…) | yes | – |
idempotency_key | string | no | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters) |
dry_run | boolean | no | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false) |
- Idempotency: the result returns the
idempotency_keyused, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours). - Dry run: supported.
dry_run: truechecks permissions and rules and computes the result, then rolls everything back.
Errors
validation_failed: The installation is revoked.oauth_client_disabled: The organization that registered the app disabled it for good: uninstall it.app_suspended: Ownrecord suspended the app: it can't be resumed until it is reinstated.installer_not_eligible: The installer still has no access: re-assign the app first.resource_not_found: No installation with this ID exists in the organization.version_conflict: The installation changed at the same moment; retry.permission_denied: You can't manage the organization's apps.
Example
Resume an app
Arguments:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"object": "app_installation",
"orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
"app": {
"id": "ocl_01m4ttwd3veh9apbewxheq5xha",
"name": "Ledgerly AI",
"publisher": "Ledgerly AI B.V.",
"logoUrl": null,
"verified": true,
"status": "active",
"suspension": null
},
"installedBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
"scopes": ["filings:read", "filings:write", "tasks:read", "tasks:write"],
"limitTo": {
"entityIds": ["ent_01m4ttwd3veh9apbewxheq5xh4"],
"brandIds": []
},
"limits": {
"rps": null,
"mutationsPerDay": null,
"amountLimits": []
},
"status": "active",
"pausedReason": null,
"pausedAt": null,
"revokedAt": null,
"createdAt": "2026-10-25T09:00:00.000Z",
"updatedAt": "2026-10-26T14:30:00.000Z"
}
app_installations_revoke
Uninstall an app. Operation app_installations.revoke · Organization level · permission agents:admin · risk tier security · since M10
Uninstalls an app from the organization: its tokens stop working there at once and the installation is kept
as revoked with its audit trail. The app can be installed again later through the consent screen.
Uninstalling an uninstalled app changes nothing.
Annotations: readOnlyHint: false · destructiveHint: true · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID (ains_…) | yes | – |
idempotency_key | string | no | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters) |
dry_run | boolean | no | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false) |
- Idempotency: the result returns the
idempotency_keyused, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours). - Dry run: supported.
dry_run: truechecks permissions and rules and computes the result, then rolls everything back.
Errors
resource_not_found: No installation with this ID exists in the organization.version_conflict: The installation changed at the same moment; retry.permission_denied: You can't manage the organization's apps.
Example
Uninstall an app
Arguments:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"object": "app_installation",
"orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
"app": {
"id": "ocl_01m4ttwd3veh9apbewxheq5xha",
"name": "Ledgerly AI",
"publisher": "Ledgerly AI B.V.",
"logoUrl": null,
"verified": true,
"status": "active",
"suspension": null
},
"installedBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
"scopes": ["filings:read", "filings:write", "tasks:read", "tasks:write"],
"limitTo": {
"entityIds": ["ent_01m4ttwd3veh9apbewxheq5xh4"],
"brandIds": []
},
"limits": {
"rps": null,
"mutationsPerDay": null,
"amountLimits": []
},
"status": "revoked",
"pausedReason": null,
"pausedAt": null,
"revokedAt": "2026-10-26T14:30:00.000Z",
"createdAt": "2026-10-25T09:00:00.000Z",
"updatedAt": "2026-10-26T14:30:00.000Z"
}
app_installations_update
Narrow an installed app's access. Operation app_installations.update · Organization level · permission agents:admin · risk tier security · since M10
Changes what an installed app may do in the organization: fewer scopes (only scopes it already has; more need
the app to ask for consent again), a different limitTo (entities or brands; empty lists = the whole
organization), or its limits. Changes apply to the app's next call. A revoked installation can't be changed.
limits work as an agent's (spec §41.4): rps operation calls per second (agent_rate_limited),
mutationsPerDay changes per UTC day and mode (agent_daily_limit_reached), and amountLimits per financial
operation and currency (perCall, perDay; money as integer micros in a string): a call above them, or
without an amount, creates an approval request instead of running. Send only what changes; null clears a
value.
Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID (ains_…) | yes | – |
scopes | array of one of 84 values, e.g. org:read, org:write, org:admin | no | (1–200 items) |
limitTo | object | no | – |
limits | object | no | – |
idempotency_key | string | no | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters) |
dry_run | boolean | no | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false) |
- Idempotency: the result returns the
idempotency_keyused, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours). - Dry run: supported.
dry_run: truechecks permissions and rules and computes the result, then rolls everything back.
Errors
validation_failed: A scope isn't one the installation already has, or a limit can't work (e.g. an amount limit on an operation that moves no amount).resource_not_found: No such installation, or an entity or brand in limitTo doesn't exist.version_conflict: The installation changed at the same moment; retry.permission_denied: You can't manage the organization's apps.
Examples
Read-only filings
Arguments:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"scopes": ["filings:read", "tasks:read"],
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"object": "app_installation",
"orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
"app": {
"id": "ocl_01m4ttwd3veh9apbewxheq5xha",
"name": "Ledgerly AI",
"publisher": "Ledgerly AI B.V.",
"logoUrl": null,
"verified": true,
"status": "active",
"suspension": null
},
"installedBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
"scopes": ["filings:read", "tasks:read"],
"limitTo": {
"entityIds": ["ent_01m4ttwd3veh9apbewxheq5xh4"],
"brandIds": []
},
"limits": {
"rps": null,
"mutationsPerDay": null,
"amountLimits": []
},
"status": "active",
"pausedReason": null,
"pausedAt": null,
"revokedAt": null,
"createdAt": "2026-10-25T09:00:00.000Z",
"updatedAt": "2026-10-26T14:30:00.000Z"
}
Ten changes a day, refunds up to €100 a day
Arguments:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"limits": {
"mutationsPerDay": 10,
"amountLimits": [
{
"operationId": "refunds.create",
"perDay": {
"amount": "100000000",
"currency": "EUR"
}
}
]
},
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"id": "ains_01m4ttwd3veh9apbewxheq5xhc",
"object": "app_installation",
"orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
"app": {
"id": "ocl_01m4ttwd3veh9apbewxheq5xha",
"name": "Ledgerly AI",
"publisher": "Ledgerly AI B.V.",
"logoUrl": null,
"verified": true,
"status": "active",
"suspension": null
},
"installedBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
"scopes": ["filings:read", "filings:write", "tasks:read", "tasks:write"],
"limitTo": {
"entityIds": ["ent_01m4ttwd3veh9apbewxheq5xh4"],
"brandIds": []
},
"limits": {
"rps": null,
"mutationsPerDay": 10,
"amountLimits": [
{
"operationId": "refunds.create",
"perCall": null,
"perDay": {
"amount": "100000000",
"currency": "EUR"
}
}
]
},
"status": "active",
"pausedReason": null,
"pausedAt": null,
"revokedAt": null,
"createdAt": "2026-10-25T09:00:00.000Z",
"updatedAt": "2026-10-26T14:30:00.000Z"
}