Skip to content
ApiqDevelopers
API v1.64.0Open console
API referenceidentity

Approve mcp grant request

POST/v1/mcp/grant-requests/{requestId}:approve
Accepts bearer

The signed-in human approves an MCP grant for themselves

HUMAN CONSOLE SESSION ONLY: an API key, a service token and an MCP grant-derived token are 403 PERMISSION_DENIED details.reason SESSION_REQUIRED, so an agent can never approve its own grant.Show moreHUMAN CONSOLE SESSION ONLY: an API key, a service token and an MCP grant-derived token are 403 PERMISSION_DENIED details.reason SESSION_REQUIRED, so an agent can never approve its own grant. The grant is bound to the approving human and to the session (refresh family) the approval came from: logout, logout-all, a password change or reset, user disable, tenant SUSPENDED or OFFBOARDED and session reuse detection all end it. The tenant must be ACTIVE (a SUSPENDED tenant is 403 TENANT_SUSPENDED), the tenant's console toolset switch ON (getMcpSettings; OFF is 403 PERMISSION_DENIED details.reason TOOLSET_DISABLED) and grants enabled on the rung (else 403 PERMISSION_DENIED details.reason GRANTS_DISABLED). A request that is no longer PENDING is 409 CONFLICT details.reason WRONG_STATE. For an authorization-code request the answer carries redirectTo, the client's redirect_uri with code, state and iss, and the browser goes exactly there; the code is single-use and lives 60 s. For a device flow the answer is {approved: true} and the agent's next poll receives the tokens. A grant never reaches a route outside its toolset's read operations, and never one the human cannot reach now. writeOperations, a subset of the request's offered writeOperations, gives write consent for those console commit-lite tools; it needs the step-up proof (stepUpCode or stepUpAssertion; absent 403 STEP_UP_REQUIRED, wrong STEP_UP_FAILED). A ticked write runs only while the tenant keeps it ON, the platform and plane write ceilings are on and the human holds its permission; money and decisions stay unreachable. Emits mcp.grant.approved and writes the audit row mcp.grant.approve (writeOperations, stepUp).

Path parameters

  • requestIdstringRequired
    A pending MCP grant request id, from the consent redirect (?request=) or a user-code lookup.Show moreA pending MCP grant request id, from the consent redirect (?request=) or a user-code lookup. Opaque and unguessable: at least 128 bits from a cryptographic random source, never a sequential or monotonic id, because it is the only handle in the consent URL.

Request body

  • toolsetstringRequired
    Must equal the request's toolset; on a device flow the human selects it by hand
    • console
    • supplier
    • operator
  • operationsarray of stringOptional
  • writeOperationsarray of stringOptional
    Console only: the write tools ticked, a subset of the request's writeOperations (any other name is 400 VALIDATION details.reason OPERATION_NOT_ALLOWED, field writeOperations); absent or empty = no…Show moreConsole only: the write tools ticked, a subset of the request's writeOperations (any other name is 400 VALIDATION details.reason OPERATION_NOT_ALLOWED, field writeOperations); absent or empty = no write consent. Non-empty needs the step-up proof
  • crossTenantReadsarray of stringOptional
    Operator only: the cross-tenant reads ticked, a subset of the request's crossTenantReads; absent or empty = none (the default)
  • confirmOwnDevicebooleanOptional
    Required true on a device flow ("I started this on my own device")
  • stepUpCodestringOptional
    The approving human's current TOTP code. Send this or stepUpAssertion, not both
  • stepUpAssertionobjectOptional
    A WebAuthn step-up assertion. Send this or stepUpCode, not both
    5 child attributes
    • idstringRequired
      The credential id, base64url
    • rawIdstringRequired
      The credential id, base64url
    • typestringRequired
      • public-key
    • responseobjectRequired
      4 child attributes
      • clientDataJSONstringRequired
        base64url
      • authenticatorDatastringRequired
        base64url
      • signaturestringRequired
        base64url
      • userHandlestringOptional
        base64url, or null when the authenticator returns none
    • clientExtensionResultsobjectOptional

Responses

  • 200ApprovedMcpGrantRequestDecision
  • 400
    VALIDATION on approveMcpGrantRequest, supplierApproveMcpGrantRequest and opsApproveMcpGrantRequest: toolset missing or not the request's (details.reason TOOLSET_MISMATCH), an operation outside the…Show moreVALIDATION on approveMcpGrantRequest, supplierApproveMcpGrantRequest and opsApproveMcpGrantRequest: toolset missing or not the request's (details.reason TOOLSET_MISMATCH), an operation outside the request's list or an empty list (OPERATION_NOT_ALLOWED, details.field operations), a write tool or a cross-tenant read the request did not offer, or a device flow without confirmOwnDevice true (OWN_DEVICE_CONFIRMATION_REQUIRED).
    ApiErrorResponse
  • 401
    UNAUTHENTICATED — missing or expired token.Show moreUNAUTHENTICATED — missing or expired token. Declared on every operation because `security` is declared globally at the document root: every route is authenticated, so every route can answer 401.
    ApiErrorResponse
  • 403ApiErrorResponse
  • 404NOT_FOUND — unknown or expired ref (unguessable refs, 15)ApiErrorResponse
  • 405
    VALIDATION — the public edge serves GET, POST, PUT, PATCH and DELETE only; any other method is refused before the platform sees it (details.reason METHOD_NOT_ALLOWED, details.source edge).Show moreVALIDATION — the public edge serves GET, POST, PUT, PATCH and DELETE only; any other method is refused before the platform sees it (details.reason METHOD_NOT_ALLOWED, details.source edge). Not retryable as sent.
    ApiErrorResponse
  • 409CONFLICT details.reason WRONG_STATE — the grant request is no longer PENDING (already approved or denied, expired, or, for an operator request, AWAITING_SECOND_APPROVAL); details.state says which.ApiErrorResponse
  • 413
    VALIDATION — the request body is larger than the surface's limit.Show moreVALIDATION — the request body is larger than the surface's limit. Not retryable as sent: shrink the body. Declared on every operation that takes a request body. details carries exactly one key, maxBodyBytes (integer): the limit that applies to this surface, in bytes.
    ApiErrorResponse
  • 414
    VALIDATION — the request URI (path and query string) is longer than 8 KiB; the public edge refuses it before the platform sees it (details.reason URI_TOO_LONG, details.source edge).Show moreVALIDATION — the request URI (path and query string) is longer than 8 KiB; the public edge refuses it before the platform sees it (details.reason URI_TOO_LONG, details.source edge). Not retryable as sent: send long input in the body of a POST.
    ApiErrorResponse
  • 415
    VALIDATION — a request body that is not JSON (application/json or application/*+json; a form body only on the OAuth token routes).Show moreVALIDATION — a request body that is not JSON (application/json or application/*+json; a form body only on the OAuth token routes). The public edge refuses it before the platform sees it (details.reason UNSUPPORTED_MEDIA_TYPE, details.source edge). Not retryable as sent: send Content-Type application/json. Declared on every operation that takes a JSON request body.
    ApiErrorResponse
  • 500INTERNAL — a bug, and traceId is the support handle.ApiErrorResponse

Errors you should handle

Branch on code and honour retryable — never on the HTTP status alone.

400VALIDATION
Select the toolset this agent asked for before approving.
not retryable
401UNAUTHENTICATED
The bearer token is expired. Re-authenticate and retry.
not retryable
403PERMISSION_DENIED
Approving agent connections needs a signed-in person. An agent cannot read or approve its own connection.
not retryable
403TENANT_SUSPENDED
This organisation is suspended; new agent connections are refused.
not retryable
404NOT_FOUND
searchRef SR-F-7b31d0a9 is unknown or has expired; re-search
not retryable
405VALIDATION
This method is not served.
not retryable
409CONFLICT
This agent connection request has already been decided.
not retryable
413VALIDATION
The request body is larger than this API accepts (262144 bytes).
not retryable
414VALIDATION
The request URI is longer than 8 KiB.
not retryable
415VALIDATION
Send application/json.
not retryable
500INTERNAL
An unexpected error occurred. Quote the traceId to support.
retryable