# Create/Refresh Access Token Create or refresh an access token to make requests on behalf of a user. This endpoint is used to obtain an `access_token` and `refresh_token` for the first time, and to refresh the `access_token` when it expires. This endpoint is part of OAuth 2.0 implementation. You need to configure OAuth App to obtain `client_id` and `client_secret`. Read more about [OAuth 2.0 implementation](https://developers.pandadoc.com/reference/authentication-process). Make sure you're sending the header `Content-Type: application/x-www-form-urlencoded`. ## Create Access Token As a result of the OAuth 2.0 user authentication process, you should get a `code` that can be exchanged for an `access_token`. Use this endpoint to do this exchange, and to refresh the token later. > 🚧 Invalid Grant? > > If you receive an `invalid grant` response it is likely because you used the same `code` more than once from the [Authorize a PandaDoc User](ref:authorize-a-user) step above. The `code` parameter is generated for one-time use. A new `code` value must be generated if you wish to change API users, permissions, or simply generate a new `code` value for the same PandaDoc user. > 📘 expires_in > > `expires_in` is based in seconds. Currently, a token expires in 31535999 seconds = 1 year. ## Refresh Access Token Eventually, `access_token` expires and accessing an API method returns **401 unauthorized**. Your application needs to refresh the OAuth2 token with the stored `refresh_token` returned when initially creating an access token. Once refreshed, calls on behalf of the originally authorized user can resume immediately. Use the newly returned `access_token` for all future API requests. > 🚧 Invalid Grant? > > If you receive an `invalid grant` response, it is likely because your `refresh_token` is invalid. # OpenAPI definition ```json { "openapi": "3.0.3", "info": { "title": "PandaDoc Public API", "description": "PandaDoc API spans a broad range of functionality to help you build incredible documents automation experiences inside your product.\n\nPandaDoc API is organized around REST. Our API has predictable resource-oriented URLs and uses standard HTTP response codes, authentication, and verbs.\n\n## Getting started\n\nYou can start testing PandaDoc API with a sandbox key on our [Enterprise](https://www.pandadoc.com/pricing/) plan, either active or in trial.\n\nGenerate your [sandbox key](https://developers.pandadoc.com/reference/sandbox-key) on the Developer Dashboard with predefined [rate limits](https://developers.pandadoc.com/reference/limits). Or contact our solutions expert if you work with high-transaction volumes.\n\n## Guides\n\nIf you’re just getting started with PandaDoc, you may want to jump straight into one of our [getting started guides](https://developers.pandadoc.com/docs/getting-started) for the feature you’re most interested in, whether that’s:\n\n- [Create from template](https://developers.pandadoc.com/docs/create-send-document),\n- [Upload and send a local PDF](https://developers.pandadoc.com/docs/upload-and-send-a-local-pdf),\n- or [Listening for changes in document status](https://developers.pandadoc.com/docs/listen-document-status-changes).\n\nWe also recommend you to discover our dynamic content generation on a fly: [Create from a template with content placeholder](https://developers.pandadoc.com/docs/create-with-content-placeholders-from-template).\n", "termsOfService": "https://www.pandadoc.com/master-services-agreement/", "contact": { "name": "PandaDoc API Support", "url": "https://developers.pandadoc.com/", "email": "api-track@pandadoc.com" }, "license": { "name": "MIT", "url": "https://github.com/PandaDoc/pandadoc-openapi-specification/blob/main/LICENSE" }, "version": "7.18.2" }, "servers": [ { "url": "https://api.pandadoc.com", "description": "Public API" } ], "security": [ { "apiKey": [] }, { "oauth2": [] } ], "tags": [ { "name": "OAuth 2.0 Authentication", "description": "Operations for creating and refreshing access tokens for user authentication." } ], "paths": { "/oauth2/access_token": { "post": { "summary": "Create/Refresh Access Token", "operationId": "accessToken", "security": [], "description": "Create or refresh an access token to make requests on behalf of a user. This endpoint is used to obtain an `access_token` and `refresh_token` for the first time, and to refresh the `access_token` when it expires.\nThis endpoint is part of OAuth 2.0 implementation. You need to configure OAuth App to obtain `client_id` and `client_secret`. Read more about [OAuth 2.0 implementation](https://developers.pandadoc.com/reference/authentication-process).\nMake sure you're sending the header `Content-Type: application/x-www-form-urlencoded`. \n\n## Create Access Token\nAs a result of the OAuth 2.0 user authentication process, you should get a `code` that can be exchanged for an `access_token`. Use this endpoint to do this exchange, and to refresh the token later.\n\n> 🚧 Invalid Grant?\n> \n> If you receive an `invalid grant` response it is likely because you used the same `code` more than once from the [Authorize a PandaDoc User](https://developers.pandadoc.com/reference/authorize-a-user) step above. The `code` parameter is generated for one-time use. A new `code` value must be generated if you wish to change API users, permissions, or simply generate a new `code` value for the same PandaDoc user.\n\n> 📘 expires_in\n> \n> `expires_in` is based in seconds. Currently, a token expires in 31535999 seconds = 1 year.\n\n## Refresh Access Token\nEventually, `access_token` expires and accessing an API method returns **401 unauthorized**. Your application needs to refresh the OAuth2 token with the stored `refresh_token` returned when initially creating an access token.\n\nOnce refreshed, calls on behalf of the originally authorized user can resume immediately. Use the newly returned `access_token` for all future API requests.\n\n> 🚧 Invalid Grant?\n> \n> If you receive an `invalid grant` response, it is likely because your `refresh_token` is invalid.\n", "tags": [ "OAuth 2.0 Authentication" ], "requestBody": { "required": true, "content": { "application/x-www-form-urlencoded": { "schema": { "oneOf": [ { "$ref": "#/components/schemas/OAuth2CreateAccessTokenRequest" }, { "$ref": "#/components/schemas/OAuth2RefreshAccessTokenRequest" } ] }, "examples": { "Create Access Token": { "value": { "grant_type": "authorization_code", "client_id": "8f0a1b2c3d4e5f6g7h8i9j", "client_secret": "k1l2m3n4o5p6q7r8s9t0u", "code": "v9w8x7y6z5a4b3c2d1e0f", "scope": "read+write" } }, "Refresh Access Token": { "value": { "grant_type": "refresh_token", "client_id": "89b2d1ea5f7c3b0a19456", "client_secret": "e7c390f1ba8d2a6b57910c4d3b2a1e0f9d8c7b6a", "refresh_token": "9a4b5c6d7e8f0g1h2i3j4k5l6m7n8o9p0q1r2s3t", "scope": "read+write" } } } } } }, "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OAuth2AccessTokenResponse" } } } }, "400": { "description": "Bad Request", "content": { "application/json": { "schema": { "properties": { "error": { "type": "string", "example": "unsupported_grant_type" } } } } } } } } } }, "components": { "securitySchemes": { "apiKey": { "type": "apiKey", "name": "Authorization", "in": "header", "description": "The `Authorization` header must contain the API key. The value should be prefixed with `API-Key` followed by a space and the actual API key.\n", "x-default": "API-Key 3039ba033eb1410caa0a2227158d63c9d6502cd8" }, "oauth2": { "type": "oauth2", "flows": { "authorizationCode": { "authorizationUrl": "https://app.pandadoc.com/oauth2/authorize", "tokenUrl": "https://api.pandadoc.com/oauth2/access_token", "refreshUrl": "https://api.pandadoc.com/oauth2/access_token", "scopes": { "read+write": "Use `read+write` to create, send, delete, and download documents, and `read` to view templates and document details." } } }, "description": "Send the authenticating user to the PandaDoc OAuth2 request URL. We recommend a button or a link titled\n\"Connect to PandaDoc\" if you are connecting users from a custom application. Users will see the \"Authorize Application\" screen.\nWhen the user clicks \"Authorize\", PandaDoc redirects the user back to your site with an authorization code inside the URL.\n\nhttps://app.pandadoc.com/oauth2/authorize?client_id={client_id}&redirect_uri={redirect_uri}&scope=read+write&response_type=code\n\n`client_id` and `redirect_uri` values should match your application settings.\n" } }, "schemas": { "OAuth2CreateAccessTokenRequest": { "type": "object", "title": "Create Access Token", "properties": { "grant_type": { "type": "string", "description": "This value must be set to `authorization_code`.", "default": "authorization_code" }, "client_id": { "type": "string", "description": "Client ID that is automatically generated after application creation in the Developer Dashboard.", "example": "479a3c7ba4a8d3cf28702" }, "client_secret": { "type": "string", "description": "Client secret that is automatically generated after application creation in the Developer Dashboard.", "example": "a66515d3caf9183b8cad3eee546bcba892b45b01" }, "code": { "type": "string", "description": "`auth_code` from the server on the previous step (Authorize a PandaDoc User).\n", "example": "a9a60d4dabb61ade665c712d2b41766e7bb9a2f9" }, "scope": { "type": "string", "description": "Requested permissions. Use `read+write` to create, send, delete, and download documents, and `read` to view templates and document details.", "example": "read+write" } }, "required": [ "grant_type", "client_id", "client_secret", "code" ] }, "OAuth2RefreshAccessTokenRequest": { "type": "object", "title": "Refresh Access Token", "properties": { "grant_type": { "type": "string", "description": "This value must be set to `refresh_token`.", "default": "refresh_token" }, "client_id": { "type": "string", "description": "Client ID that is automatically generated after application creation in the Developer Dashboard.", "example": "479a3c7ba4a8d3cf28702" }, "client_secret": { "type": "string", "description": "Client secret that is automatically generated after application creation in the Developer Dashboard.", "example": "a66515d3caf9183b8cad3eee546bcba892b45b01" }, "refresh_token": { "type": "string", "description": "`refresh_token` you received and stored from the server when initially creating an `access_token`.\n", "example": "f61cc0cffd437c9a596f0acc8eb6f502a7a429d7" }, "scope": { "type": "string", "description": "Requested permissions. Use `read+write` as our default value to send documents.", "example": "read+write" } }, "required": [ "grant_type", "client_id", "client_secret", "refresh_token" ] }, "OAuth2AccessTokenResponse": { "type": "object", "properties": { "access_token": { "type": "string", "example": "2ff2dfe36322448c6953616740a910be57bbd4ca" }, "token_type": { "type": "string", "example": "Bearer" }, "expires_in": { "type": "number", "example": 31535999 }, "scope": { "type": "string", "example": "read+write" }, "refresh_token": { "type": "string", "example": "4c82f23d91a75961f4d08134fc5ad0dfe6a4c36a" } } } } } } ```