Skip to content

Create an org agent

The agents.create operation: POST /api/v1/agents in the REST API and the agents_create tool in the MCP server.

POST/api/v1/agents

Creates an agent: a machine identity for the organization's own AI agents and automations. It holds one role at a scope (the organization, one legal entity or one brand), like a member, and gets access tokens with OAuth 2.1 client_credentials at /oauth/token.

  • authMethod: "client_secret_basic" (default): the response contains the client secret in credentials.clientSecret. It is shown only once; only a hash is stored.
  • authMethod: "private_key_jwt": give your public keys in jwks; the agent signs a client assertion instead of sending a secret.

scopes are the permission scopes its tokens may carry (default: everything the role can use at that scope). An agent is test mode only until livemodeAccess is turned on, whatever its role. It never gets more than you have yourself at its scope and mode (agent_delegation_not_allowed), never org_owner, and never decides approval requests. limits (requests per second, mutations per day, amounts per financial operation) and toolSets (the MCP tool sets it sees: workflows, registry or operation areas such as tasks; none means all of them) are applied by the runtime.

dpopBoundAccessTokens: true makes every token sender-constrained: the token endpoint refuses a request without a DPoP proof (invalid_grant), so a leaked token is useless without the agent's private key.

At a glance

  • REST: POST /api/v1/agents
  • MCP tool: agents_create
  • Operation ID: agents.create
  • Scope: Organization
  • Permission: agents:admin
  • Risk tier: security
  • Dry run: Supported (send Ownrecord-Dry-Run: true)
  • Idempotency: Idempotency-Key required
  • Modes: Test and live
  • Authentication: API key with the agents:admin scope
  • Fresh sign-in: In the console, a sign-in within the last 15 minutes
  • Since: M10

Request

Body

A JSON object (Content-Type: application/json):

FieldTypeRequiredDescription
namestringYes
descriptionstringNo
contactstringNo
vendorstringNo
roleone of org_admin, billing_admin, finance, tax_manager, support, developer, viewerYes
scopeobjectNo
livemodeAccessbooleanNo
scopesarray of one of 84 values, e.g. org:read, org:write, org:admin (all in the OpenAPI document)No
authMethodone of client_secret_basic, private_key_jwtNo
jwksobjectNo
jwks.keysarray of objectYes
jwks.keys[].ktyone of RSA, EC, OKPYes
jwks.keys[].kidstringNo
jwks.keys[].use"sig"No
jwks.keys[].algstringNo
dpopBoundAccessTokensbooleanNoRequire DPoP for every token: a token request without a DPoP proof is refused (RFC 9449).
limitsobjectNo
limits.rpsinteger (1 to 10000) or nullNo
limits.mutationsPerDayinteger (0 to 10000000) or nullNo
limits.amountLimitsarray of objectNo
limits.amountLimits[].operationIdstringYes
limits.amountLimits[].perCallmoney or nullNo
limits.amountLimits[].perDaymoney or nullNo
toolSetsarray of stringNo

Response

201 Created with a JSON object:

FieldTypeDescription
agentobject
agent.idagt_… ID
agent.object"agent"
agent.orgIdorg_… ID
agent.namestring
agent.descriptionstring or null
agent.contactstring or null
agent.vendorstring or null
agent.ownerTypeone of org, app
agent.appInstallationIdains_… ID or null
agent.roleone of org_admin, billing_admin, finance, tax_manager, support, developer, viewer
agent.scopeobject
agent.livemodeAccessboolean
agent.limitsobject
agent.limits.rpsinteger or null
agent.limits.mutationsPerDayinteger or null
agent.limits.amountLimitsarray of object
agent.limits.amountLimits[].operationIdstring
agent.limits.amountLimits[].perCallmoney or null
agent.limits.amountLimits[].perDaymoney or null
agent.toolSetsarray of string
agent.statusone of active, paused, revoked
agent.clientIdocl_… ID
agent.authMethodone of client_secret_basic, client_secret_post, private_key_jwt
agent.secretPrefixstring or null
agent.dpopBoundAccessTokensboolean
agent.scopesarray of one of 84 values, e.g. org:read, org:write, org:admin (all in the OpenAPI document)
agent.createdBystring
agent.createdAtstring
agent.updatedAtstring
agent.pausedAtstring or null
agent.revokedAtstring or null
credentialsobject
credentials.clientIdocl_… ID
credentials.clientSecretstring or null
credentials.tokenEndpointstring
credentials.authMethodone of none, client_secret_basic, client_secret_post, private_key_jwt

Examples

A bookkeeping agent with a client secret

HTTP
POST /api/v1/agents
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "name": "Bookkeeper",
  "description": "Prepares and files the quarterly OSS return",
  "contact": "ops@acme.example",
  "vendor": "In-house, Claude via the MCP server",
  "role": "finance",
  "scopes": [
    "filings:read",
    "filings:write",
    "tasks:read",
    "tasks:write"
  ],
  "limits": {
    "amountLimits": [
      {
        "operationId": "refunds.create",
        "perDay": {
          "amount": "200000000",
          "currency": "EUR"
        }
      }
    ]
  }
}

Response (201):

JSON
{
  "agent": {
    "id": "agt_01m4ttwd3veh9apbewxheq5xh8",
    "object": "agent",
    "orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
    "name": "Bookkeeper",
    "description": "Prepares and files the quarterly OSS return",
    "contact": "ops@acme.example",
    "vendor": "In-house, Claude via the MCP server",
    "ownerType": "org",
    "appInstallationId": null,
    "role": "finance",
    "scope": {
      "type": "org"
    },
    "livemodeAccess": false,
    "limits": {
      "rps": null,
      "mutationsPerDay": null,
      "amountLimits": [
        {
          "operationId": "refunds.create",
          "perCall": null,
          "perDay": {
            "amount": "200000000",
            "currency": "EUR"
          }
        }
      ]
    },
    "toolSets": [],
    "status": "active",
    "clientId": "ocl_01m4ttwd3veh9apbewxheq5xh9",
    "authMethod": "client_secret_basic",
    "secretPrefix": "or_cs_Exampl",
    "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": "or_cs_ExampleOnlyNotARealSecret0000000000000000",
    "tokenEndpoint": "https://ownrecord.io/oauth/token",
    "authMethod": "client_secret_basic"
  }
}

An agent for one brand with a private key JWT

HTTP
POST /api/v1/agents
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "name": "Support triage",
  "role": "support",
  "scope": {
    "type": "brand",
    "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5"
  },
  "authMethod": "private_key_jwt",
  "jwks": {
    "keys": [
      {
        "kty": "EC",
        "crv": "P-256",
        "kid": "triage-1",
        "x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
        "y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"
      }
    ]
  }
}

Response (201):

JSON
{
  "agent": {
    "id": "agt_01m4ttwd3veh9apbewxheq5xh8",
    "object": "agent",
    "orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
    "name": "Support triage",
    "description": null,
    "contact": null,
    "vendor": null,
    "ownerType": "org",
    "appInstallationId": null,
    "role": "support",
    "scope": {
      "type": "brand",
      "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5"
    },
    "livemodeAccess": false,
    "limits": {
      "rps": null,
      "mutationsPerDay": null,
      "amountLimits": []
    },
    "toolSets": [],
    "status": "active",
    "clientId": "ocl_01m4ttwd3veh9apbewxheq5xh9",
    "authMethod": "private_key_jwt",
    "secretPrefix": null,
    "dpopBoundAccessTokens": false,
    "scopes": ["customers:read", "customers: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"
  }
}

Errors

CodeHTTP statusWhenWhat to do
validation_failed400A field is invalid, e.g. a scope the role can't use, or private_key_jwt without public keys.Fix the fields listed in details.issues and send the request again.
agent_role_invalid400The role is org_owner, or isn't allowed at the scope's type.Choose a role other than org_owner, at a scope the role allows (org, entity or brand; see the role table in the docs).
agent_delegation_not_allowed403The agent would get a permission (or live access) you don't have at its scope.Choose a narrower role, scope or token scopes, turn off live mode for the agent, or ask an organization owner to do it.
resource_not_found404The scope's entity or brand doesn't exist in the organization.Check the ID and that your credentials are scoped to the right organization, entity, brand and mode.
permission_denied403You can't manage agents, or you aren't a person or an org management key.Ask an organization owner or admin for a role or scope that allows this action.
fresh_auth_required403Your last sign-in is older than 15 minutes.Sign in again, then repeat the action within 15 minutes.

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.