Rotate an org agent's client secret
The agents.rotate_secret operation: POST /api/v1/agents/{id}/rotate_secret in the REST API and the agents_rotate_secret tool in the MCP server.
/api/v1/agents/{id}/rotate_secretReplaces the agent's client secret. The response contains the new secret in credentials.clientSecret, shown
only once; the old secret stops working at once. Access tokens already issued keep working until they expire
(15 minutes): pause the agent to revoke them too. Only agents that authenticate with a secret have one;
private_key_jwt agents rotate their keys with agents.update.
At a glance
- REST:
POST /api/v1/agents/{id}/rotate_secret - MCP tool:
agents_rotate_secret - Operation ID:
agents.rotate_secret - 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 - Fresh sign-in: In the console, a sign-in within the last 15 minutes
- Since: M10
Request
Path parameters
| Field | Type | Description |
|---|---|---|
id | agt_… ID |
Body
This operation takes no body.
Response
200 OK with a JSON object:
| Field | Type | Description |
|---|---|---|
agent | object | |
agent.id | agt_… ID | |
agent.object | "agent" | |
agent.orgId | org_… ID | |
agent.name | string | |
agent.description | string or null | |
agent.contact | string or null | |
agent.vendor | string or null | |
agent.ownerType | one of org, app | |
agent.appInstallationId | ains_… ID or null | |
agent.role | one of org_admin, billing_admin, finance, tax_manager, support, developer, viewer | |
agent.scope | object | |
agent.livemodeAccess | boolean | |
agent.limits | object | |
agent.limits.rps | integer or null | |
agent.limits.mutationsPerDay | integer or null | |
agent.limits.amountLimits | array of object | |
agent.limits.amountLimits[].operationId | string | |
agent.limits.amountLimits[].perCall | money or null | |
agent.limits.amountLimits[].perDay | money or null | |
agent.toolSets | array of string | |
agent.status | one of active, paused, revoked | |
agent.clientId | ocl_… ID | |
agent.authMethod | one of client_secret_basic, client_secret_post, private_key_jwt | |
agent.secretPrefix | string or null | |
agent.dpopBoundAccessTokens | boolean | |
agent.scopes | array of one of 84 values, e.g. org:read, org:write, org:admin (all in the OpenAPI document) | |
agent.createdBy | string | |
agent.createdAt | string | |
agent.updatedAt | string | |
agent.pausedAt | string or null | |
agent.revokedAt | string or null | |
credentials | object | |
credentials.clientId | ocl_… ID | |
credentials.clientSecret | string or null | |
credentials.tokenEndpoint | string | |
credentials.authMethod | one of none, client_secret_basic, client_secret_post, private_key_jwt |
Examples
Rotate a leaked secret
POST /api/v1/agents/agt_01m4ttwd3veh9apbewxheq5xh8/rotate_secret
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Response (200):
{
"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-26T14:30:00.000Z",
"pausedAt": null,
"revokedAt": null
},
"credentials": {
"clientId": "ocl_01m4ttwd3veh9apbewxheq5xh9",
"clientSecret": "or_cs_ExampleOnlyNotARealSecret0000000000000000",
"tokenEndpoint": "https://ownrecord.io/oauth/token",
"authMethod": "client_secret_basic"
}
}
Errors
| Code | HTTP status | When | What to do |
|---|---|---|---|
validation_failed | 400 | The agent authenticates with private_key_jwt and has no secret. | Fix the fields listed in details.issues and send the request again. |
agent_revoked | 409 | The agent is revoked. | Create a new agent instead. |
resource_not_found | 404 | No agent with this ID exists in the organization. | Check the ID and that your credentials are scoped to the right organization, entity, brand and mode. |
version_conflict | 409 | The agent changed at the same moment; retry. | Fetch the object again and retry the change. |
permission_denied | 403 | You can't manage agents. | Ask an organization owner or admin for a role or scope that allows this action. |
fresh_auth_required | 403 | Your 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.