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.
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 integration to act on behalf of a user. You must first obtain user authorization and get an authorization code.
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(opens in a new tab or window), the
{credentials}
string must be a Base64 encoded value of{client id}:{client secret}
. - Body parameters: Provide your integration's credentials using the
client_id
andclient_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 integration's backend, otherwise they'll be blocked by Canva's Cross-Origin Resource Sharing (CORS)(opens in a new tab or window) policy.
Generate an access token using an authorization code
To generate an access token with an authorization code, you must:
- Set
grant_type
toauthorization_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 integration.
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
torefresh_token
. - Provide the
refresh_token
from a previous token request.
HTTP method and URL path
https://api.canva.com /rest /v1 /oauth /token
Authentication
This endpoint uses HTTP basic access authentication and requires no scopes.
Header parameters
Content-Type
string
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
grant_type
string
This can be one of the following:
authorization_code
: For exchanging an authorization code for an access token.refresh_token
: For generating an access token using a refresh token.
code_verifier
string
The code_verifier
value that you generated when creating the user authorization URL.
code
string
The authorization code you received after the user authorized the integration.
refresh_token
string
The refresh token to be exchanged. You can copy this value from the successful response received when generating an access token.
client_id
string
Your integration's unique ID, for authenticating the request.
We recommend that you use basic access authentication instead of specifying client_id
and client_secret
as body parameters.
client_secret
string
Your integration's client secret, for authenticating the request. Begins with cnvca
.
We recommend that you use basic access authentication instead of specifying client_id
and client_secret
as body parameters.
redirect_uri
string
Only required if a redirect URL was supplied when you created the user 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.
scope
string
Optional scope value when refreshing an access token. Separate multiple 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:
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'
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));
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<String> response = HttpClient.newHttpClient().send(request,HttpResponse.BodyHandlers.ofString());System.out.println(response.body());}}
import requestsheaders = {"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())
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);};
package mainimport ("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))}
$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;}
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 = truerequest = 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:
access_token
string
The bearer access token to use to authenticate to Canva Connect API endpoints. If requested using a authorization_code
or refresh_token
, this allows you to act on behalf of a user.
refresh_token
string
The token that you can use to refresh the access token.
token_type
string
The token type returned. This is always Bearer
.
expires_in
integer
The expiry time (in seconds) for the token.
scope
string
The scopes that the token has been granted.
Example response
{"access_token": "JagALLazU0i2ld9WW4zTO4kaG0lkvP8Y5sSO206ZwxNF4E1y3xKJKF7TzN17BXTfaNOeY0P88AeRCE6cRF7SJzvf3Sx97rA80sGHtFplFo","refresh_token": "JABix5nolsk9k8n2r0f8nq1gw4zjo40ht6sb4i573wgdzmkwdmiy6muh897hp0bxyab276wtgqkvtob2mg9aidt5d6rcltcbcgs101","token_type": "Bearer","expires_in": 14400,"scope": "asset:read design:meta:read design:permission:read folder:read"}