Summary and recommendation
PagerDuty exposes a REST API v2 at https://api.pagerduty.com with full CRUD on users, contact methods, and notification rules. Authentication uses a Bearer token passed as 'Authorization: Token token=<YOUR_TOKEN>'; all requests must include the 'Accept: application/vnd.pagerduty+json;version=2' header or response behavior is undefined.
Account-level tokens carry full access; user-level tokens are scoped to that user's permissions, and GET /users/me returns 404 with an account-level token. The API rate limit is 960 requests per minute per token - not per IP - so distributing load across multiple tokens increases effective throughput.
For teams building identity graph pipelines or automating lifecycle across multiple SaaS tools, the PagerDuty REST API integrates cleanly into an MCP server with 60+ deep IT/identity integrations, enabling cross-system user state correlation without additional glue code.
API quick reference
| Has user API | Yes |
| Auth method | API Token (Bearer) — both account-level tokens and user-level tokens supported. OAuth 2.0 is also supported for third-party app integrations. |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Business or Enterprise |
Authentication
Auth method: API Token (Bearer) - both account-level tokens and user-level tokens supported. OAuth 2.0 is also supported for third-party app integrations.
Setup steps
- Log in to PagerDuty as an Admin or Account Owner.
- Navigate to Integrations > API Access Keys.
- Click 'Create New API Key', provide a description, and choose Read-only or Full Access.
- Copy the generated token - it is shown only once.
- Include the token in all requests as the Authorization header: 'Authorization: Token token=
'. - For OAuth 2.0: register an app under Developer Mode, obtain client_id/client_secret, and follow the authorization code flow to obtain a Bearer token.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| read | Read-only access to all account resources including users | List users, Get user, List user contact methods |
| write | Full read/write access to all account resources | Create user, Update user, Delete user, Manage contact methods and notification rules |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| id | string | Unique user identifier | auto-generated | immutable | Format: P-XXXXXXX |
| name | string | Full display name of the user | required | optional | |
| string | User's login email address | required | optional | Must be unique within the account | |
| role | string | Account-level role | optional | optional | Enum: admin, limited_user, observer, owner, read_only_user, read_only_limited_user, restricted_access, user |
| time_zone | string | User's time zone (IANA format) | optional | optional | Defaults to account time zone |
| color | string | Color used for the user's avatar | optional | optional | |
| avatar_url | string | URL of the user's avatar image | read-only | read-only | |
| description | string | Free-text description or job title | optional | optional | |
| contact_methods | array | List of contact method objects (email, phone, SMS, push) | read-only | managed via sub-resource | Use /users/{id}/contact_methods endpoints |
| notification_rules | array | List of notification rule objects | read-only | managed via sub-resource | Use /users/{id}/notification_rules endpoints |
| teams | array | Teams the user belongs to | read-only | managed via team membership endpoints | |
| invitation_sent | boolean | Whether an invitation email has been sent | auto | read-only | |
| job_title | string | User's job title | optional | optional | |
| billed | boolean | Whether the user counts as a billed seat | read-only | read-only | |
| type | string | Object type, always 'user' | required | required | Must be set to 'user' in request body |
| self | string | API URL of the user resource | read-only | read-only | |
| html_url | string | PagerDuty web UI URL for the user | read-only | read-only |
Core endpoints
List Users
- Method: GET
- URL:
https://api.pagerduty.com/users - Watch out for: Use the 'query' param to filter by name/email. 'include[]' param can expand contact_methods, notification_rules, teams. Max limit=100.
Request example
GET /users?limit=25&offset=0&query=john
Authorization: Token token=YOUR_TOKEN
Accept: application/vnd.pagerduty+json;version=2
Response example
{
"users": [{"id":"P1A2B3C","name":"John Doe","email":"john@example.com","role":"user"}],
"offset": 0,
"limit": 25,
"more": false,
"total": 1
}
Get User
- Method: GET
- URL:
https://api.pagerduty.com/users/{id} - Watch out for: Use include[] to sideload related objects; without it, contact_methods and notification_rules arrays are empty.
Request example
GET /users/P1A2B3C?include[]=contact_methods
Authorization: Token token=YOUR_TOKEN
Accept: application/vnd.pagerduty+json;version=2
Response example
{
"user": {
"id": "P1A2B3C",
"name": "John Doe",
"email": "john@example.com",
"role": "user",
"time_zone": "America/New_York"
}
}
Create User
- Method: POST
- URL:
https://api.pagerduty.com/users - Watch out for: The 'from' header (From: admin@example.com) is required for audit trail purposes on some account configurations. An invitation email is automatically sent to the new user.
Request example
POST /users
Authorization: Token token=YOUR_TOKEN
Content-Type: application/json
{"user":{"type":"user","name":"Jane Smith","email":"jane@example.com","role":"user","time_zone":"UTC"}}
Response example
{
"user": {
"id": "P9X8Y7Z",
"name": "Jane Smith",
"email": "jane@example.com",
"role": "user",
"invitation_sent": true
}
}
Update User
- Method: PUT
- URL:
https://api.pagerduty.com/users/{id} - Watch out for: PUT replaces the full user object. Always include 'type':'user' in the body. Changing role to 'owner' is not allowed via API.
Request example
PUT /users/P9X8Y7Z
Authorization: Token token=YOUR_TOKEN
Content-Type: application/json
{"user":{"type":"user","name":"Jane Smith","role":"admin"}}
Response example
{
"user": {
"id": "P9X8Y7Z",
"name": "Jane Smith",
"role": "admin"
}
}
Delete User
- Method: DELETE
- URL:
https://api.pagerduty.com/users/{id} - Watch out for: Users cannot be deleted if they are the only member of an on-call schedule or escalation policy. Remove them from all schedules/policies first. Deletion is permanent.
Request example
DELETE /users/P9X8Y7Z
Authorization: Token token=YOUR_TOKEN
Accept: application/vnd.pagerduty+json;version=2
Response example
HTTP 204 No Content
List User Contact Methods
- Method: GET
- URL:
https://api.pagerduty.com/users/{id}/contact_methods - Watch out for: Contact method types: email_contact_method, phone_contact_method, sms_contact_method, push_notification_contact_method. Phone/SMS require E.164 format.
Request example
GET /users/P1A2B3C/contact_methods
Authorization: Token token=YOUR_TOKEN
Accept: application/vnd.pagerduty+json;version=2
Response example
{
"contact_methods": [
{"id":"CM1","type":"email_contact_method","address":"john@example.com","label":"Default"}
]
}
Create User Contact Method
- Method: POST
- URL:
https://api.pagerduty.com/users/{id}/contact_methods - Watch out for: Phone and SMS contact methods require country_code as an integer. Push notification contact methods cannot be created via API - they are registered by the mobile app.
Request example
POST /users/P1A2B3C/contact_methods
Content-Type: application/json
{"contact_method":{"type":"sms_contact_method","country_code":1,"address":"5551234567","label":"Mobile"}}
Response example
{
"contact_method": {
"id": "CM2",
"type": "sms_contact_method",
"address": "5551234567",
"label": "Mobile"
}
}
Get Current User
- Method: GET
- URL:
https://api.pagerduty.com/users/me - Watch out for: Only works with user-level API tokens, not account-level tokens. Returns 404 with account-level tokens.
Request example
GET /users/me
Authorization: Token token=USER_LEVEL_TOKEN
Accept: application/vnd.pagerduty+json;version=2
Response example
{
"user": {
"id": "P1A2B3C",
"name": "John Doe",
"email": "john@example.com",
"role": "admin"
}
}
Rate limits, pagination, and events
- Rate limits: PagerDuty enforces rate limits per API token. Standard limit is 960 requests per minute. Limits are communicated via response headers.
- Rate-limit headers: Yes
- Retry-After header: Yes
- Rate-limit notes: When rate limited, the API returns HTTP 429. The Retry-After header indicates seconds to wait. Headers X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset are included in responses.
- Pagination method: offset
- Default page size: 25
- Max page size: 100
- Pagination pointer: offset and limit; response includes 'more' boolean and 'total' count
| Plan | Limit | Concurrent |
|---|---|---|
| All plans | 960 requests/minute per API token | 0 |
- Webhooks available: Yes
- Webhook notes: PagerDuty Webhooks v3 (current) deliver HTTP POST payloads to configured endpoints for account events. User-specific events are limited; most webhook events are incident/service-focused.
- Alternative event strategy: For comprehensive user lifecycle events, use SCIM provisioning with an IdP (Okta, Entra ID, OneLogin) which provides real-time sync. Alternatively, poll GET /users on a schedule.
- Webhook events: user.created, user.updated, user.deleted
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Business or Enterprise
Endpoint: https://app.pagerduty.com/scim/v2
Supported operations: GET /Users - list users, GET /Users/{id} - get user, POST /Users - create user, PUT /Users/{id} - replace user, PATCH /Users/{id} - update user (including deactivate via active=false), DELETE /Users/{id} - delete user, GET /Groups - list teams, POST /Groups - create team, PATCH /Groups/{id} - update team membership, DELETE /Groups/{id} - delete team
Limitations:
- Requires SSO (SAML) to be configured before SCIM can be enabled.
- Business plan or higher required; not available on Free or Professional plans.
- SCIM token is separate from REST API tokens - generated in SSO settings.
- User role assignment via SCIM is limited; advanced role mapping may require REST API.
- Push notification contact methods cannot be managed via SCIM.
- SCIM Groups map to PagerDuty Teams, not escalation policies or schedules.
Common scenarios
Three scenarios cover the majority of programmatic user lifecycle needs. First, provisioning a new user with an SMS contact method requires three sequential calls: POST /users (capture the returned id), POST /users/{id}/contact_methods (SMS requires country_code as an integer and E.
164-compatible number without the '+' prefix), then POST /users/{id}/notification_rules referencing the contact method id. The 'From' header (acting admin email) is required on POST /users for audit trail compliance on many account configurations - omitting it can produce a 400.
Second, deprovisioning requires dependency resolution before deletion: GET /users/{id}? include[]=teams, then DELETE /teams/{team_id}/users/{user_id} for each team, followed by a schedule and escalation policy audit via GET /schedules and GET /escalation_policies.
DELETE /users/{id} returns 400 if the user is the sole member of any on-call schedule layer or escalation policy step - automate this dependency check or deletions will fail silently in batch jobs.
Third, SCIM sync with Okta uses base URL https://app.pagerduty.com/scim/v2 with a SCIM-specific Bearer token generated under SSO settings - entirely separate from REST API tokens and not visible on the API Access Keys page.
Provision a new user with SMS contact method and notification rule
- POST /users with name, email, role, time_zone, and type='user' to create the user. Note the returned user id.
- POST /users/{id}/contact_methods with type='sms_contact_method', country_code, address (phone number), and label.
- Note the returned contact_method id.
- POST /users/{id}/notification_rules with start_delay_in_minutes, contact_method reference (id + type), and urgency ('high' or 'low').
Watch out for: Include the 'From' header on POST /users. SMS contact methods require E.164-compatible number without '+' prefix - pass country_code separately as integer.
Deprovision a user (offboarding)
- GET /users/{id}?include[]=teams to identify team memberships.
- For each team, DELETE /teams/{team_id}/users/{user_id} to remove team membership.
- GET /schedules and GET /escalation_policies to check if user is referenced; remove or replace them.
- DELETE /users/{id} once the user has no blocking schedule/policy dependencies.
Watch out for: DELETE /users/{id} returns 400 if the user is the only member of any on-call schedule layer or escalation policy step. Automate dependency checks before deletion.
Sync users via SCIM with Okta
- Confirm account is on Business or Enterprise plan.
- Enable SSO/SAML in PagerDuty under Account Settings > Single Sign-On.
- Navigate to Account Settings > SCIM and generate a SCIM API token.
- In Okta, add the PagerDuty app from the Okta Integration Network.
- Configure SCIM provisioning in Okta using base URL 'https://app.pagerduty.com/scim/v2' and the SCIM token as Bearer auth.
- Enable Okta features: Push New Users, Push Profile Updates, Push Groups (maps to PagerDuty Teams).
- Assign users/groups in Okta to trigger provisioning.
Watch out for: SCIM token is distinct from REST API tokens. SSO must be fully configured and tested before enabling SCIM. Deactivating a user in Okta sets active=false in PagerDuty (suspends) but does not delete them.
Why building this yourself is a trap
The most common integration failure is conflating SCIM and REST API credential types: SCIM tokens are generated under Account Settings > Single Sign-On, not the API Access Keys page, and the two are not interchangeable.
PUT /users/{id} replaces the full user object - partial updates that omit fields will null them out, so always include 'type':'user' in the body. The 'owner' role cannot be set via API and must be changed in the web UI, which breaks fully automated provisioning flows that need to transfer account ownership.
The identity graph implication is also significant: SCIM Groups map to PagerDuty Teams, not to escalation policies or schedules, so team membership sync via SCIM does not guarantee on-call coverage is correctly assigned - that layer requires separate REST API calls and cannot be inferred from IdP group membership alone.
Automate PagerDuty workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.