> ## 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.
# Get the public keys for webhooks
API reference for the keys method.
This API is currently provided as a preview. Be aware of the following:
* There might be unannounced breaking changes.
* Any breaking changes to preview APIs won't produce a new [API version](https://www.canva.dev/docs/apps/rest-apis/versions/).
* Public apps that use preview APIs will not pass the review process, and can't be made available to all Canva users.
The Keys API (`connect/keys`) is a security measure you can use to verify the authenticity
of webhooks you receive from the Canva REST APIs. The Keys API returns a
[JSON Web Key (JWK)](https://www.rfc-editor.org/rfc/rfc7517#section-2), which you can use to
decrypt the webhook signature and verify it came from Canva and not a potentially malicious
actor. This helps to protect your systems from
[Replay attacks](https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures/).
The keys returned by the Keys API can rotate. We recommend you cache the keys you receive
from this API where possible, and only access this API when you receive a webhook signed
with an unrecognized key. This allows you to verify webhooks quicker than accessing this API
every time you receive a webhook.
## HTTP method and URL path
GET https\://api.canva.com/rest/v1/connect/keys
## Authentication and authorization
This endpoint is public and doesn't require authentication.
## Example request
Examples for using the `/v1/connect/keys` endpoint:
```sh
curl --request GET 'https://api.canva.com/rest/v1/connect/keys'
```
```js
const fetch = require("node-fetch");
fetch("https://api.canva.com/rest/v1/connect/keys", {
method: "GET",
})
.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/connect/keys"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse response = HttpClient.newHttpClient().send(
request,
HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
}
}
```
```py
import requests
response = requests.get("https://api.canva.com/rest/v1/connect/keys");
print(response.json())
```
```csharp
using System.Net.Http;
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://api.canva.com/rest/v1/connect/keys"),
};
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"
)
func main() {
url := "https://api.canva.com/rest/v1/connect/keys"
req, _ := http.NewRequest("GET", url, nil)
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/connect/keys",
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
));
$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/connect/keys')
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
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:
A Json Web Key Set (JWKS) with public keys used for signing webhooks. You can use this JWKS
to verify that a webhook was sent from Canva.
Properties of keys>} defaultExpanded={true}>
The `kid` (key ID) is a unique identifier for a public key. When the keys used
to sign webhooks are rotated, you can use this ID to select the correct key
within a JWK Set during the key rollover. The `kid` value is case-sensitive.
The `kty` (key type) identifies the cryptographic algorithm family used with
the key, such as "RSA" or "EC". Only Octet Key Pairs
(`OKPs`) are supported.
The `kty` value is case-sensitive. For more information on the `kty` property
and OKPs, see [RFC-8037 — "kty" (Key Type)
Parameter](https://www.rfc-editor.org/rfc/rfc8037.html#section-2).
The `crv` (curve) property identifies the curve used for elliptical curve
encryptions. Only "Ed25519" is supported. For more information on the `crv`
property, see [RFC-8037 — Key Type
"OKP"](https://www.rfc-editor.org/rfc/rfc8037.html#section-2).
The `x` property is the public key of an elliptical curve encryption. The key
is Base64urlUInt-encoded. For more information on the `x` property, see
[RFC-8037 — "x" (X Coordinate)
Parameter](https://www.rfc-editor.org/rfc/rfc8037#section-2).
## Example response
```json
{
"keys": [
{
"kid": "a418dc7d-ecc5-5c4b-85ce-e1104a8addbe",
"kty": "OKP",
"crv": "Ed25519",
"x": "aIQtqd0nDfB-ug0DrzZbwTum-1ITdXvKxGFak_1VB2j"
},
{
"kid": "c8de5bec1-1b88-4ddaae04acc-ce415-5d7",
"kty": "OKP",
"crv": "Ed25519",
"x": "m2d1FT-gfBXxIzKwdQVTra0D-aBq_ubZ1jI0GuvkDtn"
}
]
}
```