Sending HTTP requests

How to send HTTP requests with the Fetch capability.

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

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 requests
const response = await fetch.get({
endpoint: "/my/cool/endpoint",
});
// POST requests
const 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); // => 200
console.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 error
console.log(error);
}