Apps can send HTTP requests to a third-party server at any point in its lifecycle. This guide explains everything you need to know about sending requests.
Prerequisites
- You've set up a Base URL.
- You've registered at least one endpoint.
Initializing the Fetch capability
Like all capabilities, Canva injects the Fetch capability into the app's iframe and attaches it to the window
object:
console.log(window.canva.fetch);
You can access the capability by importing and calling the getFetch
function:
import { getFetch } from "@canva/fetch";const fetch = getFetch();console.log(fetch); // => Fetch
This function:
- Throws an error if the capability is unavailable
- Provides type-safety when using TypeScript
Sending requests
To send a request, call the get
or post
method:
// GET requestsconst response = await fetch.get({endpoint: "/my/cool/endpoint",});// POST requestsconst response = await fetch.post({endpoint: "/my/cool/endpoint",});
Both methods accept an object as their only parameter. At a minimum, this object must specify an endpoint that's registered via the Developer Portal.
The endpoint:
- Must not include the Base URL
- Must start with a leading slash
- Must not have a trailing slash
If the endpoint is invalid or if the app attempts to send a request to an endpoint that is not registered via the Developer Portal, an error is thrown. You can check the JavaScript Console to see the error.
Sending query parameters
To append query parameters to the endpoint of a GET
request, specify them via the params
property:
const response = await fetch.get({endpoint: "/my/cool/endpoint",params: {name: "David",age: "31",location: "Australia",},});
The values of the parameters must be strings.
Sending request bodies
To send data via the body of a POST
request, specify it via the body
property:
const response = await fetch.post({endpoint: "/my/cool/endpoint",body: {name: "David",age: 31,location: "Australia",},});
The body must be a JSON-compatible object. This means it must not throw an error if passed into the JSON.stringify
method.
Sending request headers
To include headers with a request, specify them via the headers
property:
const response = await fetch.post({endpoint: "/my/cool/endpoint",headers: {"X-My-Custom-Header": "This is a header",},body: {name: "David",age: 31,location: "Australia",},});
The name of each header must be prefixed with X-
, such as X-My-Custom-Header
.
Default request headers
When an app sends a request, Canva includes a number of default headers with the request. You can use these headers to implement authentication and signature verification.
The headers include:
X-Canva-Timestamp
X-Canva-Signatures
X-Canva-User-Id
X-Canva-Brand-Id
Your app must not overwrite Canva's default headers. The best way to avoid this is to not use header names that start with X-Canva-
.
Receiving requests
You can use any modern framework or programming language to receive requests from Canva. The main requirement is that the tooling can handle requests with a Content-Type
of application/json
.
This is an example of an Express.js endpoint that's setup to handle requests from Canva:
import express from "express";const app = express();app.use(express.json());app.post("/my/cool/endpoint", async (request, response) => {response.send({message: "Hello world",});});app.listen(process.env.PORT || 3000);
Handling responses
When a request is successful, the get
and post
methods return a Promise<Response>
object. This object contains the details of the response, including the status code, headers, and body:
const response = await fetch.post({endpoint: "/my/cool/endpoint",body: {name: "David",age: 31,location: "Australia",},});console.log(response.status); // => 200console.log(response.headers); // => { ... }console.log(response.body); // => { ... }
The response body is automatically parsed as JSON.
Handling errors
When the status code of a response is not 2xx, Canva considers the request to be unsuccessful and throws an error. You can use the try/catch syntax to catch and handle errors:
try {const response = await fetch.post({endpoint: "/my/cool/endpoint",});} catch (error) {// TODO: Handle the errorconsole.log(error);}