> ## Documentation Index > Fetch the complete documentation index at: https://www.canva.dev/docs/apps/llms.txt > Use this file to discover all available pages before exploring further. # Generate an access token Generate access tokens to access the Canva REST APIs. This endpoint implements the OAuth 2.0 `token` endpoint, as part of the Authorization Code flow with Proof Key for Code Exchange (PKCE). For more information, see [Authentication](https://www.canva.dev/docs/apps/rest-apis/authentication/). To generate an access token, you must provide one of the following: * An authorization code * A refresh token Generating a token using either an authorization code or a refresh token allows your app to act on behalf of a user. You must first [obtain user authorization and get an authorization code](https://www.canva.dev/docs/apps/rest-apis/authentication/#obtain-user-authorization). Access tokens may be up to 4 KB in size, and are only valid for a specified period of time. The expiry time (currently 4 hours) is shown in the endpoint response and is subject to change. **Endpoint authentication** Requests to this endpoint require authentication with your client ID and client secret, using *one* of the following methods: * **Basic access authentication** (Recommended): For [basic access authentication](https://en.wikipedia.org/wiki/Basic_access_authentication), the `{credentials}` string must be a Base64 encoded value of `{client id}:{client secret}`. * **Body parameters**: Provide your app's credentials using the `client_id` and `client_secret` body parameters. This endpoint can't be called from a user's web-browser client because it uses client authentication with client secrets. Requests must come from your app's backend, otherwise they'll be blocked by Canva's [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. **Generate an access token using an authorization code** To generate an access token with an authorization code, you must: * Set `grant_type` to `authorization_code`. * Provide the `code_verifier` value that you generated when creating the user authorization URL. * Provide the authorization code you received after the user authorized the app. **Generate an access token using a refresh token** Using the `refresh_token` value from a previous user token request, you can get a new access token with the same or smaller scope as the previous one, but with a refreshed expiry time. You will also receive a new refresh token that you can use to refresh the access token again. To refresh an existing access token, you must: * Set `grant_type` to `refresh_token`. * Provide the `refresh_token` from a previous token request. ## HTTP method and URL path POST https\://api.canva.com/rest/v1/oauth/token ## Authentication and authorization This endpoint uses HTTP basic access authentication. ## Header parameters Provides credentials to authenticate the request, in the form of [basic access authentication](https://en.wikipedia.org/wiki/Basic_access_authentication). For example: `Authorization: Basic {credentials}` NOTE: We recommend that you use basic access authentication instead of specifying `client_id` and `client_secret` as body parameters. Indicates the media type of the information sent in the request. This must be set to `application/x-www-form-urlencoded`. For example: `Content-Type: application/x-www-form-urlencoded` ## Body parameters For exchanging an authorization code for an access token. For exchanging an authorization code for an access token. **Available values:** The only valid value is `authorization_code`. The `code_verifier` value that you generated when creating the user authorization URL. The authorization code you received after the user authorized the app. Your app's unique ID, for authenticating the request. NOTE: We recommend that you use basic access authentication instead of specifying `client_id` and `client_secret` as body parameters. Your app's client secret, for authenticating the request. Begins with `cnvca`. NOTE: We recommend that you use basic access authentication instead of specifying `client_id` and `client_secret` as body parameters. Only required if a redirect URL was supplied when you [created the user authorization URL](https://www.canva.dev/docs/apps/rest-apis/authentication/#create-the-authorization-url). Must be one of those already specified by the client. If not supplied, the first redirect\_uri defined for the client will be used by default. For generating an access token using a refresh token. For generating an access token using a refresh token. **Available values:** The only valid value is `refresh_token`. The refresh token to be exchanged. You can copy this value from the successful response received when generating an access token. Your app's unique ID, for authenticating the request. NOTE: We recommend that you use basic access authentication instead of specifying `client_id` and `client_secret` as body parameters. Your app's client secret, for authenticating the request. Begins with `cnvca`. NOTE: We recommend that you use basic access authentication instead of specifying `client_id` and `client_secret` as body parameters. Optional scope value when refreshing an access token. Separate multiple [scopes](https://www.canva.dev/docs/apps/rest-apis/scopes/) with a single space between each scope. The requested scope cannot include any permissions not already granted, so this parameter allows you to limit the scope when refreshing a token. If omitted, the scope for the token remains unchanged. ## Example request Examples for using the `/v1/oauth/token` endpoint: ```sh curl --request POST 'https://api.canva.com/rest/v1/oauth/token' \ --header 'Authorization: Basic {credentials}' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=authorization_code' \ --data-urlencode 'code_verifier=i541qdcfkb4htnork0w92lnu43en99ls5a48ittv6udqgiflqon8vusojojakbq4' \ --data-urlencode 'code=kp8nnroja7qnx00.opyc1p76rcbyflsxbycjqfp3ub8vzsvltpzwafy9q5l45dn5fxzhe7i7a6mg1i2t8jpsa6sebdeumkzzhicskabgevrxsssec4dvjwfvhq4gs3ugghguar0voiqpfb7axsapiojoter8v3w2s5s3st84jpv2l06h667iw241xngy9c8=vu1tnjp7sz' \ --data-urlencode 'redirect_uri=https://example.com/process-auth' ``` ```js const fetch = require("node-fetch"); const { URLSearchParams } = require("url"); fetch("https://api.canva.com/rest/v1/oauth/token", { method: "POST", headers: { "Authorization": "Basic {credentials}", "Content-Type": "application/x-www-form-urlencoded", }, body: new URLSearchParams("grant_type=authorization_code&code_verifier=i541qdcfkb4htnork0w92lnu43en99ls5a48ittv6udqgiflqon8vusojojakbq4&code=kp8nnroja7qnx00.opyc1p76rcbyflsxbycjqfp3ub8vzsvltpzwafy9q5l45dn5fxzhe7i7a6mg1i2t8jpsa6sebdeumkzzhicskabgevrxsssec4dvjwfvhq4gs3ugghguar0voiqpfb7axsapiojoter8v3w2s5s3st84jpv2l06h667iw241xngy9c8%3Dvu1tnjp7sz&redirect_uri=https%3A%2F%2Fexample.com%2Fprocess-auth"), }) .then(async (response) => { const data = await response.json(); console.log(data); }) .catch(err => console.error(err)); ``` ```java import java.io.IOException; import java.net.URI; import java.net.http.*; public class ApiExample { public static void main(String[] args) throws IOException, InterruptedException { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://api.canva.com/rest/v1/oauth/token")) .header("Authorization", "Basic {credentials}") .header("Content-Type", "application/x-www-form-urlencoded") .method("POST", HttpRequest.BodyPublishers.ofString("grant_type=authorization_code&code_verifier=i541qdcfkb4htnork0w92lnu43en99ls5a48ittv6udqgiflqon8vusojojakbq4&code=kp8nnroja7qnx00.opyc1p76rcbyflsxbycjqfp3ub8vzsvltpzwafy9q5l45dn5fxzhe7i7a6mg1i2t8jpsa6sebdeumkzzhicskabgevrxsssec4dvjwfvhq4gs3ugghguar0voiqpfb7axsapiojoter8v3w2s5s3st84jpv2l06h667iw241xngy9c8%3Dvu1tnjp7sz&redirect_uri=https%3A%2F%2Fexample.com%2Fprocess-auth")) .build(); HttpResponse response = HttpClient.newHttpClient().send( request, HttpResponse.BodyHandlers.ofString() ); System.out.println(response.body()); } } ``` ```py import requests headers = { "Authorization": "Basic {credentials}", "Content-Type": "application/x-www-form-urlencoded" } data = { "grant_type": "authorization_code", "code_verifier": "i541qdcfkb4htnork0w92lnu43en99ls5a48ittv6udqgiflqon8vusojojakbq4" "code": "kp8nnroja7qnx00.opyc1p76rcbyflsxbycjqfp3ub8vzsvltpzwafy9q5l45dn5fxzhe7i7a6mg1i2t8jpsa6sebdeumkzzhicskabgevrxsssec4dvjwfvhq4gs3ugghguar0voiqpfb7axsapiojoter8v3w2s5s3st84jpv2l06h667iw241xngy9c8=vu1tnjp7sz", "redirect_uri": "https://example.com/process-auth", } response = requests.post("https://api.canva.com/rest/v1/oauth/token", headers=headers, data=data ) print(response.json()) ``` ```csharp using System.Net.Http; var client = new HttpClient(); var request = new HttpRequestMessage { Method = HttpMethod.Post, RequestUri = new Uri("https://api.canva.com/rest/v1/oauth/token"), Headers = { { "Authorization", "Basic {credentials}" }, }, Content = new StringContent( "grant_type=authorization_code&code_verifier=i541qdcfkb4htnork0w92lnu43en99ls5a48ittv6udqgiflqon8vusojojakbq4&code=kp8nnroja7qnx00.opyc1p76rcbyflsxbycjqfp3ub8vzsvltpzwafy9q5l45dn5fxzhe7i7a6mg1i2t8jpsa6sebdeumkzzhicskabgevrxsssec4dvjwfvhq4gs3ugghguar0voiqpfb7axsapiojoter8v3w2s5s3st84jpv2l06h667iw241xngy9c8%3Dvu1tnjp7sz&redirect_uri=https%3A%2F%2Fexample.com%2Fprocess-auth", Encoding.UTF8, "application/x-www-form-urlencoded" ), }; using (var response = await client.SendAsync(request)) { response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body); }; ``` ```go package main import ( "fmt" "io" "net/http" "strings" ) func main() { payload := strings.NewReader("grant_type=authorization_code&code_verifier=i541qdcfkb4htnork0w92lnu43en99ls5a48ittv6udqgiflqon8vusojojakbq4&code=kp8nnroja7qnx00.opyc1p76rcbyflsxbycjqfp3ub8vzsvltpzwafy9q5l45dn5fxzhe7i7a6mg1i2t8jpsa6sebdeumkzzhicskabgevrxsssec4dvjwfvhq4gs3ugghguar0voiqpfb7axsapiojoter8v3w2s5s3st84jpv2l06h667iw241xngy9c8%3Dvu1tnjp7sz&redirect_uri=https%3A%2F%2Fexample.com%2Fprocess-auth") url := "https://api.canva.com/rest/v1/oauth/token" req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Basic {credentials}") req.Header.Add("Content-Type", "application/x-www-form-urlencoded") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } ``` ```php $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "https://api.canva.com/rest/v1/oauth/token", CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => array( 'Authorization: Basic {credentials}', 'Content-Type: application/x-www-form-urlencoded', ), CURLOPT_POSTFIELDS => "grant_type=authorization_code&code_verifier=i541qdcfkb4htnork0w92lnu43en99ls5a48ittv6udqgiflqon8vusojojakbq4&code=kp8nnroja7qnx00.opyc1p76rcbyflsxbycjqfp3ub8vzsvltpzwafy9q5l45dn5fxzhe7i7a6mg1i2t8jpsa6sebdeumkzzhicskabgevrxsssec4dvjwfvhq4gs3ugghguar0voiqpfb7axsapiojoter8v3w2s5s3st84jpv2l06h667iw241xngy9c8%3Dvu1tnjp7sz&redirect_uri=https%3A%2F%2Fexample.com%2Fprocess-auth" )); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if (empty($err)) { echo $response; } else { echo "Error: " . $err; } ``` ```ruby require 'net/http' require 'uri' url = URI('https://api.canva.com/rest/v1/oauth/token') http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request['Authorization'] = 'Basic {credentials}' request['Content-Type'] = 'application/x-www-form-urlencoded' request.body = "grant_type=authorization_code&code_verifier=i541qdcfkb4htnork0w92lnu43en99ls5a48ittv6udqgiflqon8vusojojakbq4&code=kp8nnroja7qnx00.opyc1p76rcbyflsxbycjqfp3ub8vzsvltpzwafy9q5l45dn5fxzhe7i7a6mg1i2t8jpsa6sebdeumkzzhicskabgevrxsssec4dvjwfvhq4gs3ugghguar0voiqpfb7axsapiojoter8v3w2s5s3st84jpv2l06h667iw241xngy9c8%3Dvu1tnjp7sz&redirect_uri=https%3A%2F%2Fexample.com%2Fprocess-auth" response = http.request(request) puts response.read_body ``` ## Success response If successful, the endpoint returns a `200` response with a JSON body with the following parameters: The bearer access token to use to authenticate to Canva REST API endpoints. If requested using a `authorization_code` or `refresh_token`, this allows you to act on behalf of a user. The token that you can use to refresh the access token. The token type returned. This is always `Bearer`. The expiry time (in seconds) for the access token. The [scopes](https://www.canva.dev/docs/apps/rest-apis/scopes/) that the token has been granted. ## Example response ```json { "access_token": "JagALLazU0i2ld9WW4zTO4kaG0lkvP8Y5sSO206ZwxNF4E1y3xKJKF7TzN17BXTfaNOeY0P88AeRCE6cRF7SJzvf3Sx97rA80sGHtFplFo", "refresh_token": "JABix5nolsk9k8n2r0f8nq1gw4zjo40ht6sb4i573wgdzmkwdmiy6muh897hp0bxyab276wtgqkvtob2mg9aidt5d6rcltcbcgs101", "token_type": "Bearer", "expires_in": 14400, "scope": "asset:read design:meta:read design:permission:read folder:read" } ``` ## Error responses ### 400 Bad Request A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see [Error responses](/docs/apps/rest-apis/error-responses/). A human-readable description of what went wrong. #### Example error responses ##### client\_id body parameter has multiple values ```json { "code": "invalid_field", "message": "client_id body param must have a single value" } ``` ##### client\_id body parameter is blank or empty ```json { "code": "invalid_field", "message": "client_id body param must not be blank or empty" } ``` ##### client\_secret body parameter has multiple values ```json { "code": "invalid_field", "message": "client_secret body param must have a single value" } ``` ##### client\_id basic auth parameter is blank or empty ```json { "code": "invalid_field", "message": "client_id basic auth parameter must not be blank or empty" } ``` ##### secret basic auth parameter is blank or empty ```json { "code": "invalid_field", "message": "secret basic auth parameter must not be blank or empty" } ``` ##### Request body too large ```json { "code": "bad_request_body", "message": "Request body too large" } ``` ##### The refresh token is invalid. ```json { "code": "invalid_grant", "message": "Invalid refresh token" } ``` ##### The client must be authenticated using basic auth or body parameters. ```json { "code": "unauthorized_client", "message": "The client must either be authenticated using basic auth or body parameters." } ``` ##### The token exchange request is invalid. ```json { "code": "invalid_request", "message": "{description}" } ``` ##### The provided authorization grant is invalid, expired, or revoked. ```json { "code": "invalid_grant", "message": "{description}" } ``` ##### The client is not authorized to use this grant type. ```json { "code": "unauthorized_client", "message": "{description}" } ``` ##### The grant type is not supported. ```json { "code": "unsupported_grant_type", "message": "{description}" } ``` ##### The requested scope is invalid, unknown, or malformed. ```json { "code": "invalid_scope", "message": "{description}" } ``` ### 401 Unauthorized A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see [Error responses](/docs/apps/rest-apis/error-responses/). A human-readable description of what went wrong. #### Example error responses ##### Client secret is invalid (Unauthorized) ```json { "code": "invalid_access_token", "message": "Client secret is invalid for {clientAppId}" } ``` ##### Access token is missing ```json { "code": "invalid_access_token", "message": "Access token is missing" } ``` ##### The client credentials are invalid. ```json { "code": "invalid_client", "message": "{description}" } ``` ##### The user is not authorized. ```json { "code": "unauthorized_user", "message": "{description}" } ``` ### 429 Too Many Requests A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see [Error responses](/docs/apps/rest-apis/error-responses/). A human-readable description of what went wrong. #### Example error response ##### Too many token exchange requests. ```json { "code": "too_many_requests", "message": "Too many {grantType} requests" } ```