Install an app (consent)
The app_installations.create operation: POST /api/v1/app_installations in the REST API and the app_installations_create tool in the MCP server.
/api/v1/app_installationsInstalls 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.
At a glance
- REST:
POST /api/v1/app_installations - MCP tool:
app_installations_create - Operation ID:
app_installations.create - Scope: Organization
- Permission:
agents:admin - Risk tier:
security - Dry run: Supported (send
Ownrecord-Dry-Run: true) - Idempotency:
Idempotency-Keyrequired - Modes: Test and live
- Authentication: API key with the
agents:adminscope - Since: M10
Request
Body
A JSON object (Content-Type: application/json):
| Field | Type | Required | Description |
|---|---|---|---|
clientId | ocl_… ID | Yes | |
grantId | ogr_… ID | Yes | |
scopes | array of one of 84 values, e.g. org:read, org:write, org:admin (all in the OpenAPI document) | Yes | |
limitTo | object | No | |
limitTo.entityIds | array of ent_… ID | No | |
limitTo.brandIds | array of brd_… ID | No |
Response
201 Created with a JSON object:
| Field | Type | Description |
|---|---|---|
id | ains_… ID | |
object | "app_installation" | |
orgId | org_… ID | |
app | object | |
app.id | ocl_… ID | |
app.name | string | |
app.publisher | string | |
app.logoUrl | string or null | |
app.verified | boolean | |
app.status | one of active, disabled | |
app.suspension | object or null | |
installedBy | usr_… ID | |
scopes | array of one of 84 values, e.g. org:read, org:write, org:admin (all in the OpenAPI document) | |
limitTo | object | |
limitTo.entityIds | array of ent_… ID | |
limitTo.brandIds | array of brd_… ID | |
limits | object | |
limits.rps | integer or null | |
limits.mutationsPerDay | integer or null | |
limits.amountLimits | array of object | |
limits.amountLimits[].operationId | string | |
limits.amountLimits[].perCall | money or null | |
limits.amountLimits[].perDay | money or null | |
status | one of active, paused, revoked | |
pausedReason | one of manual, installer_lost_access, platform_suspended, app_disabled or null | |
pausedAt | string or null | |
revokedAt | string or null | |
createdAt | string | |
updatedAt | string |
Examples
Install for one legal entity
POST /api/v1/app_installations
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json
{
"clientId": "ocl_01m4ttwd3veh9apbewxheq5xha",
"grantId": "ogr_01m4ttwd3veh9apbewxheq5xhd",
"scopes": [
"filings:read",
"filings:write",
"tasks:read",
"tasks:write"
],
"limitTo": {
"entityIds": [
"ent_01m4ttwd3veh9apbewxheq5xh4"
]
}
}
Response (201):
{
"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"
}
Errors
| Code | HTTP status | When | What to do |
|---|---|---|---|
validation_failed | 400 | A scope isn't one the app registered, or a field is invalid. | Fix the fields listed in details.issues and send the request again. |
app_not_installable | 400 | The app is private to another organization, or listed but not (yet) approved in platform review. | Ask the app's publisher to list it: private apps install only in the organization that registered them, and other organizations can install a listed app once platform review has approved it. |
app_scopes_not_approved | 403 | Another organization's listed app: a scope its approved listing doesn't cover (it waits for re-review). | Consent only to the scopes platform review approved (details.approved). The others wait for the publisher's re-review; they can be added after it is approved. |
oauth_client_disabled | 409 | The app is disabled. | Register a new app, or create a new agent. |
app_suspended | 409 | Ownrecord suspended the app: nothing installs it while the suspension lasts. | The app can't be installed, resumed or authorized while the suspension lasts. Its organization's owners and admins, and those of every organization that installed it, were emailed the reason. Once Ownrecord reinstates it, resume its installation under Organization → Agents & apps. |
oauth_grant_mismatch | 400 | The grant isn't yours or isn't the app's. | Start the authorization again from the application. |
resource_not_found | 404 | The app, or an entity or brand in limitTo, doesn't exist. | Check the ID and that your credentials are scoped to the right organization, entity, brand and mode. |
permission_denied | 403 | You can't install apps, or this isn't a signed-in person. | Ask an organization owner or admin for a role or scope that allows this action. |
It can also return these common errors: api_version_unsupported, invalid_json, unsupported_media_type, authentication_required, api_key_invalid, idempotency_key_required, idempotency_key_reused, idempotency_in_progress, approval_required, approval_rejected, approval_expired, stale_approval, approval_policy_denied, rate_limited, internal_error.