Skip to content

Reject an approval request

The approvals.reject operation: POST /api/v1/approvals/{id}/reject in the REST API and the approvals_reject tool in the MCP server.

POST/api/v1/approvals/{id}/reject

Rejects a pending approval request with a reason. The operation never runs; the requester sees the reason and must send a new request (with a new Idempotency-Key) to try again. The same people who may approve a request may reject it, and the requester may reject (withdraw) their own request. Emits approval.resolved.

At a glance

  • REST: POST /api/v1/approvals/{id}/reject
  • MCP tool: approvals_reject
  • Operation ID: approvals.reject
  • Scope: Organization
  • Permission: approvals:write
  • Risk tier: write
  • Dry run: Supported (send Ownrecord-Dry-Run: true)
  • Idempotency: Idempotency-Key required
  • Modes: Test and live
  • Authentication: API key with the approvals:write scope
  • Since: M2

Request

Path parameters

FieldTypeDescription
idapr_… ID

Body

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

FieldTypeRequiredDescription
reasonstringYes

Response

200 OK with a JSON object:

FieldTypeDescription
idapr_… ID
object"approval_request"
statusone of pending, approved, rejected, expired, executed, stale
operationIdstring
summarystring
orgIdorg_… ID
entityIdent_… ID or null
brandIdbrd_… ID or null
livemodeboolean
requestedByobject
requestedBy.typeone of user, api_key, agent, app, system, public, customer
requestedBy.idstring
requestedBy.viaone of console, api, mcp, assistant, portal, job or null
requestedBy.clientIdstring or null
requestedBy.onBehalfOfUserIdstring or null
requestedBy.appInstallationIdstring or null
amountmoney or null
inputany
dryRunobject
dryRun.outputany
dryRun.eventsarray of string
diffobject or null
requiredApprovalsinteger (1 to 2)
approvalsarray of object
approvals[].userIdusr_… ID
approvals[].atdate-time
approvals[].commentstring or null
rejectionobject or null
failureobject or null
resultRefstring or null
approveUrlstring
expiresAtdate-time
executedAtdate-time or null
createdAtdate-time
updatedAtdate-time

Examples

Reject a brand change

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

{
  "reason": "The descriptor must match the registered name."
}

Response (200):

JSON
{
  "id": "apr_01m4ttwd3veh9apbewxheq5xh7",
  "object": "approval_request",
  "status": "rejected",
  "operationId": "brands.update",
  "summary": "Update a brand",
  "orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
  "entityId": "ent_01m4ttwd3veh9apbewxheq5xh4",
  "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
  "livemode": true,
  "requestedBy": {
    "type": "user",
    "id": "usr_01m4ttwd3veh9apbewxheq5xh6",
    "via": "console",
    "clientId": null,
    "onBehalfOfUserId": null,
    "appInstallationId": null
  },
  "amount": null,
  "input": {
    "id": "brd_01m4ttwd3veh9apbewxheq5xh5",
    "statementDescriptor": "ACME APP"
  },
  "dryRun": {
    "output": {
      "id": "brd_01m4ttwd3veh9apbewxheq5xh5",
      "statementDescriptor": "ACME APP"
    },
    "events": ["brand.updated"]
  },
  "diff": {
    "before": {
      "statementDescriptor": "ACME"
    },
    "after": {
      "statementDescriptor": "ACME APP"
    }
  },
  "requiredApprovals": 1,
  "approvals": [],
  "rejection": {
    "userId": "usr_01m4ttwd3veh9apbewxheq5xha",
    "at": "2026-10-13T14:30:00.000Z",
    "reason": "The descriptor must match the registered name."
  },
  "failure": null,
  "resultRef": null,
  "approveUrl": "https://ownrecord.io/console/acme/approvals/apr_01m4ttwd3veh9apbewxheq5xh7?mode=live",
  "expiresAt": "2026-10-16T12:00:00.000Z",
  "executedAt": null,
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-13T14:30:00.000Z"
}

Errors

CodeHTTP statusWhenWhat to do
resource_not_found404No approval request with this ID exists in this organization and mode.Check the ID and that your credentials are scoped to the right organization, entity, brand and mode.
approver_not_eligible403You can't run the operation yourself at its entity or brand in this mode, you are an API key, agent or app, or you call through an OAuth or MCP client.Approval requests are decided by people in the Ownrecord console (not API keys, agents, apps or MCP clients) who may run the operation themselves, at its entity or brand and in its mode. Ask such a person.
approval_expired409The request expired before anyone decided.Send the request again with a new Idempotency-Key to create a new approval request. Requests expire after 72 hours.
approval_not_pending409The request was already approved, rejected or run.Read the request (GET /approvals/{id}) to see its status and outcome.
version_conflict409Someone decided at the same moment; retry.Fetch the object again and retry the change.
permission_denied403You can't decide on approval requests here.Ask an organization owner or admin for a role or scope that allows this action.

It can also return these common errors: validation_failed, api_version_unsupported, invalid_json, unsupported_media_type, authentication_required, api_key_invalid, idempotency_key_required, idempotency_key_reused, idempotency_in_progress, rate_limited, internal_error.