{"__v":22,"_id":"56c515606889720d0099daf7","category":{"__v":6,"_id":"564e5a9b1560880d008d30dd","pages":["564e5a9c1560880d008d30de","56b217d91bc8490d00701f1b","56c3ccf72d97560d00e23cdc","56c515470fba010d00430759","56c515606889720d0099daf7","56d9e2106fcdd00b0002cc3f"],"project":"564e5930c3553e0d003e53d0","version":"564e5a9b1560880d008d30dc","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-11-19T23:20:17.607Z","from_sync":false,"order":0,"slug":"documentation","title":"Basics"},"parentDoc":null,"project":"564e5930c3553e0d003e53d0","user":"564e5788230d7c1700c9073e","version":{"__v":19,"_id":"564e5a9b1560880d008d30dc","project":"564e5930c3553e0d003e53d0","createdAt":"2015-11-19T23:26:19.166Z","releaseDate":"2015-11-19T23:26:19.166Z","categories":["564e5a9b1560880d008d30dd","566318e1f5ca460d00f41896","56631d08cd54d50d005015fa","56631d2a81ad7417006a202c","5668ba19fbd7680d009375f4","5668cb8b10bda80d00797ed9","5668cb9d10bda80d00797eda","56830d8a3f94e00d004e2a7a","56830d9072bb720d0091f594","56830d94cb4d190d0027698e","56830dc44aecbd0d00a464c5","569e90f3c9b43e0d00c4bab1","56a96d338791090d00113bab","56b12d8336d2580d00247877","56c36bf0a869d017002ea55b","56c36bf93d30210d00ea84bb","56c77749b935671700ff0304","56c7ab9e5652c217008e091a","56cb8bdad5c6241d00ef5e61"],"is_deprecated":false,"is_hidden":false,"is_beta":true,"is_stable":true,"codename":"Foundation","version_clean":"2.0.0","version":"2"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-02-18T00:50:40.551Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":5,"body":"Migrating your existing PagerDuty REST API v1 integration to API v2 will let you leverage greatly increased consistency to simplify your code. It will also allow your integration to take advantage of new v2-only features and functionality coming to the API in the future.\n\nA number of things have changed between API v1 and API v2. While this document covers the majority of the high-level, API-wide changes you need to be aware of, changes in specific [endpoints](#section-endpoints) are not covered comprehensively. You should consult the [API Reference](page:api-reference) for complete details of how API v2 endpoints behave.\n\nPatterns followed in API v2 were typically present in API v1, but may have been followed inconsistently across different endpoints. Review your code to determine where a pattern is already being followed and where it needs to be updated.\n[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"REST API Only\",\n  \"body\": \"This guide applies only to requests made against the PagerDuty [REST API](doc:rest-api). The format and function of the [Events API](doc:events-api) has not changed.\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Versioned Accept Header\"\n}\n[/block]\nTo make your code talk with API v2 instead of API v1, you'll need to add the [versioned PagerDuty `Accept` header](doc:versioning#section-header-based-versioning) to any API requests being made by your code:\n\n```\nAccept: application/vnd.pagerduty+json;version=2\n```\n\nHow you do this depends on the library you use to make HTTP requests, but is simple and straightforward in most libraries.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Base Path\"\n}\n[/block]\nBase paths have changed in API v2 from `https://<account-subdomain>.pagerduty.com/api/v1/` to simply `https://api.pagerduty.com/`. There's no more need to configure and store the account subdomain in order to make an API request — all you need is the authentication token.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"SSL\"\n}\n[/block]\nIn API v1, any requests made over HTTP (without SSL) would be redirected to the equivalent HTTPS endpoint.\n\nTo prevent accidentally sending sensitive information over the Internet, **API v2 requests require SSL**. Connections made over HTTP will be refused.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Authentication\"\n}\n[/block]\nThe format of the API Token `Authorization` header in v1 remains unchanged. Authentication is still required to access any REST API endpoint.\n\nSee [Authentication](doc:authentication) for the full details on authenticating to the REST API.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Rate Limiting\"\n}\n[/block]\nRate limited requests will now return a [`429 Too many requests`](http://tools.ietf.org/html/rfc6585#section-4) error code instead of [`403 Forbidden`](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4). This allows your client to distinguish between requests that fail due to insufficient permissions and requests that fail because your client is making requests too frequently.\n\nWith this change, a client *should not* retry a request that returns a `403 Forbidden` response code. These requests will only succeed if the client acquires a different key with increased permission.\n\nSee [Rate Limiting](doc:rate-limiting) for more details on API rate limiting.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Pagination\"\n}\n[/block]\nInstead of the `total` resource count field being returned by default, a new boolean field `more` will indicate whether there are more resources to be requested. You can still request the total count by passing in the parameter `total=true` as part of the query string.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Filtering\"\n}\n[/block]\nFor endpoints that allow filtering by resource `id`s, the parameter will only accept an array of `id`s and the name will be the singular form of the resource to filter on followed by `_ids`.\n\nPreviously, filters may have been specified as a comma-separated list, e.g.\n```\n/api/v1/incidents?service=PAGRDTY,PGRDUTY\n```\nIn API v2, the parameter will instead look like\n```\n/incidents?service_ids[]=PAGRDTY&service_ids[]=PGRDUTY\n```\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Includes\"\n}\n[/block]\nAll [parameters passed to the `include` array](doc:includes)  in the query string are the pluralized version of the resources to be included. Resources that are not `include`d will be presented as [resource references](doc:references).\n\nFor instance, where you may have previously used `?include[]=channel`, you should now use `?include[]=channels`.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Deleted References\"\n}\n[/block]\nNested resources that have been deleted will still be returned as part of the object, but be displayed as [resource references](doc:references), even when [included](doc:includes). These references will have a `null` value for both `self` and `html_url` as they are not accessible directly in either the web app or the API.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Wrapped Entities\"\n}\n[/block]\nAll request and response bodies contain a root-level key with the singular or plural name of the resource. In API v1, some endpoints would accept the resource's fields without this wrapping key; in API v2 these requests are invalid.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"escalation_policy\\\": {\\n    \\\"name\\\": \\\"Operations\\\",\\n    …\\n  }\\n}\",\n      \"language\": \"json\",\n      \"name\": \"Valid wrapped request in v2\"\n    },\n    {\n      \"code\": \"{\\n  \\\"name\\\": \\\"Operations\\\",\\n  …\\n}\",\n      \"language\": \"json\",\n      \"name\": \"Unwrapped request in v1 (invalid in v2)\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Resource References\"\n}\n[/block]\nIn the v1 API, relationships between resources were often specified with a `<resource>_id` field, such as `team_id` or `escalation_policy_id`. In API v2, all relationships are represented with [resource references](doc:references), which are objects that consist of an `id` field and `type` indicating the type of the object. Since every resource is also a valid resource reference, this allows you to compose request bodies by assembling entire resources together, rather than extracting the `id` field from a given resource.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"service\\\": {\\n    …\\n    \\\"escalation_policy\\\": {\\n      \\\"id\\\": \\\"PASDF12\\\",\\n      \\\"type\\\": \\\"escalation_policy\\\"\\n    },\\n  \\t…\\n  }\\n}\",\n      \"language\": \"json\",\n      \"name\": \"Valid resource reference in v2\"\n    },\n    {\n      \"code\": \"{\\n  \\\"service\\\": {\\n    …\\n    \\\"escalation_policy_id\\\": \\\"PASDF12\\\",\\n  \\t…\\n  }\\n}\",\n      \"language\": \"json\",\n      \"name\": \"_id field in v1 (invalid in v2)\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Requester\"\n}\n[/block]\nIn API v1, several endpoints provided a `requester_id` parameter, used to indicate what user the API client was acting on behalf of. This enabled an API client to acknowledge an incident on behalf of a user, invite a user on another user's behalf, etc.\n\nIn API v2, this functionality is available using the [HTTP `From:` header](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.22). Set this header with the email address of the user to act on behalf of.\n\nThis \"requester\" functionality has also been limited to endpoints where it provides significant value. Consult the [API Reference](doc:api-reference) to see if a particular endpoint accepts a `From:` header.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Endpoints\"\n}\n[/block]\nThere are a handful of larger changes to endpoints that you should be aware of when migrating.\n\n- The new `/oncalls` endpoint consolidates the functionality previously provided by several different endpoints, which are no longer available:\n  - `/users/on_call`\n  - `/users/:id/on_call`\n  - `/escalation_policies/on_call`\n  - `/schedules/:id/entries`\n- The `/alerts` endpoint has been changed to `/notifications`, and the resources within are referred to as \"notifications\". This helps distinguish between *notifications*, which are messages that PagerDuty sends to on-call users via SMS, push notification, phone call, and email, and *alerts*, which are messages generated by monitoring tools.\n- The `/users/:id/contact_methods` and `/users/:id/notification_rules` endpoints are no longer distinct endpoints. Read and manipulate a user's contact methods and notification rules by fetching and modifying `User` resources directly.\n- `/services/:id/disable` and `/services/:id/enable` have been removed. Instead, use `PUT /services` to update the service's `state` to `disabled` or `active`.","excerpt":"Migrating your existing REST API v1 client to API v2","slug":"migrating-to-api-v2","type":"basic","title":"Migrate to REST API v2"}

Migrate to REST API v2

Migrating your existing REST API v1 client to API v2

Migrating your existing PagerDuty REST API v1 integration to API v2 will let you leverage greatly increased consistency to simplify your code. It will also allow your integration to take advantage of new v2-only features and functionality coming to the API in the future. A number of things have changed between API v1 and API v2. While this document covers the majority of the high-level, API-wide changes you need to be aware of, changes in specific [endpoints](#section-endpoints) are not covered comprehensively. You should consult the [API Reference](page:api-reference) for complete details of how API v2 endpoints behave. Patterns followed in API v2 were typically present in API v1, but may have been followed inconsistently across different endpoints. Review your code to determine where a pattern is already being followed and where it needs to be updated. [block:callout] { "type": "success", "title": "REST API Only", "body": "This guide applies only to requests made against the PagerDuty [REST API](doc:rest-api). The format and function of the [Events API](doc:events-api) has not changed." } [/block] [block:api-header] { "type": "basic", "title": "Versioned Accept Header" } [/block] To make your code talk with API v2 instead of API v1, you'll need to add the [versioned PagerDuty `Accept` header](doc:versioning#section-header-based-versioning) to any API requests being made by your code: ``` Accept: application/vnd.pagerduty+json;version=2 ``` How you do this depends on the library you use to make HTTP requests, but is simple and straightforward in most libraries. [block:api-header] { "type": "basic", "title": "Base Path" } [/block] Base paths have changed in API v2 from `https://<account-subdomain>.pagerduty.com/api/v1/` to simply `https://api.pagerduty.com/`. There's no more need to configure and store the account subdomain in order to make an API request — all you need is the authentication token. [block:api-header] { "type": "basic", "title": "SSL" } [/block] In API v1, any requests made over HTTP (without SSL) would be redirected to the equivalent HTTPS endpoint. To prevent accidentally sending sensitive information over the Internet, **API v2 requests require SSL**. Connections made over HTTP will be refused. [block:api-header] { "type": "basic", "title": "Authentication" } [/block] The format of the API Token `Authorization` header in v1 remains unchanged. Authentication is still required to access any REST API endpoint. See [Authentication](doc:authentication) for the full details on authenticating to the REST API. [block:api-header] { "type": "basic", "title": "Rate Limiting" } [/block] Rate limited requests will now return a [`429 Too many requests`](http://tools.ietf.org/html/rfc6585#section-4) error code instead of [`403 Forbidden`](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4). This allows your client to distinguish between requests that fail due to insufficient permissions and requests that fail because your client is making requests too frequently. With this change, a client *should not* retry a request that returns a `403 Forbidden` response code. These requests will only succeed if the client acquires a different key with increased permission. See [Rate Limiting](doc:rate-limiting) for more details on API rate limiting. [block:api-header] { "type": "basic", "title": "Pagination" } [/block] Instead of the `total` resource count field being returned by default, a new boolean field `more` will indicate whether there are more resources to be requested. You can still request the total count by passing in the parameter `total=true` as part of the query string. [block:api-header] { "type": "basic", "title": "Filtering" } [/block] For endpoints that allow filtering by resource `id`s, the parameter will only accept an array of `id`s and the name will be the singular form of the resource to filter on followed by `_ids`. Previously, filters may have been specified as a comma-separated list, e.g. ``` /api/v1/incidents?service=PAGRDTY,PGRDUTY ``` In API v2, the parameter will instead look like ``` /incidents?service_ids[]=PAGRDTY&service_ids[]=PGRDUTY ``` [block:api-header] { "type": "basic", "title": "Includes" } [/block] All [parameters passed to the `include` array](doc:includes) in the query string are the pluralized version of the resources to be included. Resources that are not `include`d will be presented as [resource references](doc:references). For instance, where you may have previously used `?include[]=channel`, you should now use `?include[]=channels`. [block:api-header] { "type": "basic", "title": "Deleted References" } [/block] Nested resources that have been deleted will still be returned as part of the object, but be displayed as [resource references](doc:references), even when [included](doc:includes). These references will have a `null` value for both `self` and `html_url` as they are not accessible directly in either the web app or the API. [block:api-header] { "type": "basic", "title": "Wrapped Entities" } [/block] All request and response bodies contain a root-level key with the singular or plural name of the resource. In API v1, some endpoints would accept the resource's fields without this wrapping key; in API v2 these requests are invalid. [block:code] { "codes": [ { "code": "{\n \"escalation_policy\": {\n \"name\": \"Operations\",\n …\n }\n}", "language": "json", "name": "Valid wrapped request in v2" }, { "code": "{\n \"name\": \"Operations\",\n …\n}", "language": "json", "name": "Unwrapped request in v1 (invalid in v2)" } ] } [/block] [block:api-header] { "type": "basic", "title": "Resource References" } [/block] In the v1 API, relationships between resources were often specified with a `<resource>_id` field, such as `team_id` or `escalation_policy_id`. In API v2, all relationships are represented with [resource references](doc:references), which are objects that consist of an `id` field and `type` indicating the type of the object. Since every resource is also a valid resource reference, this allows you to compose request bodies by assembling entire resources together, rather than extracting the `id` field from a given resource. [block:code] { "codes": [ { "code": "{\n \"service\": {\n …\n \"escalation_policy\": {\n \"id\": \"PASDF12\",\n \"type\": \"escalation_policy\"\n },\n \t…\n }\n}", "language": "json", "name": "Valid resource reference in v2" }, { "code": "{\n \"service\": {\n …\n \"escalation_policy_id\": \"PASDF12\",\n \t…\n }\n}", "language": "json", "name": "_id field in v1 (invalid in v2)" } ] } [/block] [block:api-header] { "type": "basic", "title": "Requester" } [/block] In API v1, several endpoints provided a `requester_id` parameter, used to indicate what user the API client was acting on behalf of. This enabled an API client to acknowledge an incident on behalf of a user, invite a user on another user's behalf, etc. In API v2, this functionality is available using the [HTTP `From:` header](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.22). Set this header with the email address of the user to act on behalf of. This "requester" functionality has also been limited to endpoints where it provides significant value. Consult the [API Reference](doc:api-reference) to see if a particular endpoint accepts a `From:` header. [block:api-header] { "type": "basic", "title": "Endpoints" } [/block] There are a handful of larger changes to endpoints that you should be aware of when migrating. - The new `/oncalls` endpoint consolidates the functionality previously provided by several different endpoints, which are no longer available: - `/users/on_call` - `/users/:id/on_call` - `/escalation_policies/on_call` - `/schedules/:id/entries` - The `/alerts` endpoint has been changed to `/notifications`, and the resources within are referred to as "notifications". This helps distinguish between *notifications*, which are messages that PagerDuty sends to on-call users via SMS, push notification, phone call, and email, and *alerts*, which are messages generated by monitoring tools. - The `/users/:id/contact_methods` and `/users/:id/notification_rules` endpoints are no longer distinct endpoints. Read and manipulate a user's contact methods and notification rules by fetching and modifying `User` resources directly. - `/services/:id/disable` and `/services/:id/enable` have been removed. Instead, use `PUT /services` to update the service's `state` to `disabled` or `active`.