> For the complete documentation index, see [llms.txt](https://docs.p0.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.p0.dev/access-management/access-management/just-in-time-access/just-in-time-api/access-requests-api.md).

# Access requests API

Enable programmatic approval, denial, and revocation of access, enabling seamless integration with internal tools, bots, and security workflows for automated access escalation.

The Access Request API enables programmatic approval, denial, and revocation of access requests within the P0 platform. It is designed to support custom workflows and automation. Integrate with external systems and services to process access grants without using the P0 user interface.

This is particularly useful for integrating P0 into your internal tooling, bots, or security workflows that require automatic access escalation based on alerts, CI/CD pipelines, or external approvals.

You can also revoke many access requests in a single call — either every currently-active request for a principal, or an explicit list of request IDs — with the bulk revocation endpoint below. It's restricted to owners and API keys, supports a `dryRun` preview, and is intended for offboarding and other bulk cleanup workflows.

{% file src="/files/rSAVbzaUZ2nSPwiFXWkD" %}

## Approve an access request

> Approves a pending access request, after which P0 provisions the access. The optional body overrides the grant duration.

```json
{"openapi":"3.0.4","info":{"title":"P0 Access Requests API","version":"1.0.0"},"servers":[{"url":"https://api.p0.app"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key"}},"parameters":{"OrgId":{"name":"orgId","in":"path","required":true,"description":"The P0 organization slug, the same value that appears in console URLs at p0.app/o/{orgId}.","schema":{"type":"string"}},"RequestId":{"name":"requestId","in":"path","required":true,"description":"The ID of the access request, as returned by the Command API when the request was created.","schema":{"type":"string"}}},"schemas":{"ActionSuccess":{"type":"object","properties":{"message":{"type":"string"}}},"Error":{"type":"object","properties":{"error":{"type":"string","description":"A human-readable description of the failure."}}}},"responses":{"UnauthorizedError":{"description":"The caller could not be authenticated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ForbiddenError":{"description":"The caller is not allowed to perform this action on the request, for example the identity is not an approver under the matching access policy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFoundError":{"description":"No access request exists with this ID in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/o/{orgId}/permission-requests/{requestId}/approve":{"post":{"summary":"Approve an access request","description":"Approves a pending access request, after which P0 provisions the access. The optional body overrides the grant duration.","parameters":[{"$ref":"#/components/parameters/OrgId"},{"$ref":"#/components/parameters/RequestId"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"expirationLength":{"type":"string","description":"A P0 duration to grant instead of the requested one, for example `30m`, `2h`, or `1d`."},"isCustomExpiry":{"type":"boolean","description":"Set to `true` when `expirationLength` is not one of the organization's preset expiry options."}}}}}},"responses":{"200":{"description":"The request was approved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionSuccess"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"}}}}}}
```

## Deny an access request

> Denies a pending access request. Denial cannot be undone — the requestor must submit a new request.

```json
{"openapi":"3.0.4","info":{"title":"P0 Access Requests API","version":"1.0.0"},"servers":[{"url":"https://api.p0.app"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key"}},"parameters":{"OrgId":{"name":"orgId","in":"path","required":true,"description":"The P0 organization slug, the same value that appears in console URLs at p0.app/o/{orgId}.","schema":{"type":"string"}},"RequestId":{"name":"requestId","in":"path","required":true,"description":"The ID of the access request, as returned by the Command API when the request was created.","schema":{"type":"string"}}},"schemas":{"ActionSuccess":{"type":"object","properties":{"message":{"type":"string"}}},"Error":{"type":"object","properties":{"error":{"type":"string","description":"A human-readable description of the failure."}}}},"responses":{"UnauthorizedError":{"description":"The caller could not be authenticated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ForbiddenError":{"description":"The caller is not allowed to perform this action on the request, for example the identity is not an approver under the matching access policy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFoundError":{"description":"No access request exists with this ID in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/o/{orgId}/permission-requests/{requestId}/deny":{"post":{"summary":"Deny an access request","description":"Denies a pending access request. Denial cannot be undone — the requestor must submit a new request.","parameters":[{"$ref":"#/components/parameters/OrgId"},{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"The request was denied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionSuccess"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"}}}}}}
```

## Revoke an access grant

> Revokes an active grant before it expires. P0 automatically revokes access at expiry, so this is only needed to end a grant early. Revocation cannot be undone — the requestor must submit a new request to restore access.

```json
{"openapi":"3.0.4","info":{"title":"P0 Access Requests API","version":"1.0.0"},"servers":[{"url":"https://api.p0.app"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key"}},"parameters":{"OrgId":{"name":"orgId","in":"path","required":true,"description":"The P0 organization slug, the same value that appears in console URLs at p0.app/o/{orgId}.","schema":{"type":"string"}},"RequestId":{"name":"requestId","in":"path","required":true,"description":"The ID of the access request, as returned by the Command API when the request was created.","schema":{"type":"string"}}},"schemas":{"ActionSuccess":{"type":"object","properties":{"message":{"type":"string"}}},"Error":{"type":"object","properties":{"error":{"type":"string","description":"A human-readable description of the failure."}}}},"responses":{"UnauthorizedError":{"description":"The caller could not be authenticated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ForbiddenError":{"description":"The caller is not allowed to perform this action on the request, for example the identity is not an approver under the matching access policy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFoundError":{"description":"No access request exists with this ID in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/o/{orgId}/permission-requests/{requestId}/revoke":{"post":{"summary":"Revoke an access grant","description":"Revokes an active grant before it expires. P0 automatically revokes access at expiry, so this is only needed to end a grant early. Revocation cannot be undone — the requestor must submit a new request to restore access.","parameters":[{"$ref":"#/components/parameters/OrgId"},{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"The grant was revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionSuccess"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"}}}}}}
```

## Bulk-revoke access requests

> Revokes many access requests in one call, either every currently-active request for a principal or an explicit list of request IDs. Unlike the single-request actions above, this endpoint is restricted to owners and API keys (API keys always act as an owner). Each eligible request is revoked individually — a request that is not currently revocable is reported in \`skipped\` rather than failing the whole call. Since revocation is asynchronous, this returns \`202 Accepted\` once every request has been submitted, skipped, or found to have failed; it does not wait for deprovisioning to finish. Set \`dryRun\` to preview which requests would be affected without revoking anything.

```json
{"openapi":"3.0.4","info":{"title":"P0 Access Requests API","version":"1.0.0"},"servers":[{"url":"https://api.p0.app"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key"}},"parameters":{"OrgId":{"name":"orgId","in":"path","required":true,"description":"The P0 organization slug, the same value that appears in console URLs at p0.app/o/{orgId}.","schema":{"type":"string"}}},"schemas":{"RevocationTarget":{"oneOf":[{"type":"object","required":["type","principal"],"properties":{"type":{"type":"string","enum":["principal"]},"principal":{"type":"string","description":"Revoke every currently-active request that grants access to this principal, regardless of who requested it. Use this for offboarding, to remove all of a person's active access in one call."}}},{"type":"object","required":["type","requestIds"],"properties":{"type":{"type":"string","enum":["requests"]},"requestIds":{"type":"array","description":"The specific requests to revoke, up to 1,000 per call. Duplicate IDs are processed once.","minItems":1,"maxItems":1000,"items":{"type":"string"}}}}],"discriminator":{"propertyName":"type"}},"CreateRevocationsResponse":{"type":"object","properties":{"submitted":{"type":"array","description":"IDs of requests that were revoked (or would be, under `dryRun`).","items":{"type":"string"}},"skipped":{"type":"array","description":"Requests that matched `target` but are not currently revocable, for example because access was never provisioned or has already expired.","items":{"type":"object","properties":{"requestId":{"type":"string"},"reason":{"type":"string"}}}},"failed":{"type":"array","description":"Requests that could not be processed, for example because a requestId does not exist or the revoke itself errored.","items":{"type":"object","properties":{"requestId":{"type":"string"},"error":{"type":"string"}}}}}},"Error":{"type":"object","properties":{"error":{"type":"string","description":"A human-readable description of the failure."}}}},"responses":{"BadRequestError":{"description":"The request body failed validation, for example more than 1,000 `requestIds` or a blank `principal`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UnauthorizedError":{"description":"The caller could not be authenticated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ForbiddenError":{"description":"The caller is not allowed to perform this action on the request, for example the identity is not an approver under the matching access policy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/o/{orgId}/permission-requests/revocations":{"post":{"summary":"Bulk-revoke access requests","description":"Revokes many access requests in one call, either every currently-active request for a principal or an explicit list of request IDs. Unlike the single-request actions above, this endpoint is restricted to owners and API keys (API keys always act as an owner). Each eligible request is revoked individually — a request that is not currently revocable is reported in `skipped` rather than failing the whole call. Since revocation is asynchronous, this returns `202 Accepted` once every request has been submitted, skipped, or found to have failed; it does not wait for deprovisioning to finish. Set `dryRun` to preview which requests would be affected without revoking anything.","parameters":[{"$ref":"#/components/parameters/OrgId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["target"],"properties":{"target":{"$ref":"#/components/schemas/RevocationTarget"},"dryRun":{"type":"boolean","description":"When `true`, classify requests without revoking anything.","default":false}}}}}},"responses":{"202":{"description":"Every matched request has been submitted for revocation, skipped, or classified as failed. See the response body for the outcome of each one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRevocationsResponse"}}}},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"}}}}}}
```
