curl --request PATCH \
--url https://api.moda.app/v1/canvases/{canvas_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"description": "<string>",
"brand_kit_id": "bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV"
}
'import requests
url = "https://api.moda.app/v1/canvases/{canvas_id}"
payload = {
"name": "<string>",
"description": "<string>",
"brand_kit_id": "bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
description: '<string>',
brand_kit_id: 'bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV'
})
};
fetch('https://api.moda.app/v1/canvases/{canvas_id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.moda.app/v1/canvases/{canvas_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'description' => '<string>',
'brand_kit_id' => 'bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.moda.app/v1/canvases/{canvas_id}"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"brand_kit_id\": \"bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV\"\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.moda.app/v1/canvases/{canvas_id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"brand_kit_id\": \"bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.moda.app/v1/canvases/{canvas_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"brand_kit_id\": \"bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV\"\n}"
response = http.request(request)
puts response.read_body{
"id": "cvs_01HT9WK8N3M2J4A5Z6P7Q8R9TV",
"name": "<string>",
"url": "<string>",
"category": "<string>",
"visibility": "<string>",
"created_at": "<string>",
"updated_at": "<string>",
"created_by": {
"id": "<string>",
"name": "<string>",
"email": "<string>"
},
"template_type": "<string>",
"brand_kit_id": "<string>"
}{
"type": "invalid_request",
"code": "<string>",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"causes": [
"<unknown>"
],
"details": {},
"retry_after_ms": 123,
"retryable": true
}{
"type": "invalid_request",
"code": "<string>",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"causes": [
"<unknown>"
],
"details": {},
"retry_after_ms": 123,
"retryable": true
}{
"type": "invalid_request",
"code": "<string>",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"causes": [
"<unknown>"
],
"details": {},
"retry_after_ms": 123,
"retryable": true
}{
"type": "invalid_request",
"code": "<string>",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"causes": [
"<unknown>"
],
"details": {},
"retry_after_ms": 123,
"retryable": true
}{
"type": "invalid_request",
"code": "<string>",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"causes": [
"<unknown>"
],
"details": {},
"retry_after_ms": 123,
"retryable": true
}{
"type": "invalid_request",
"code": "<string>",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"causes": [
"<unknown>"
],
"details": {},
"retry_after_ms": 123,
"retryable": true
}{
"type": "invalid_request",
"code": "<string>",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"causes": [
"<unknown>"
],
"details": {},
"retry_after_ms": 123,
"retryable": true
}{
"type": "invalid_request",
"code": "<string>",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"causes": [
"<unknown>"
],
"details": {},
"retry_after_ms": 123,
"retryable": true
}Update Canvas
Update a canvas’s name, description, template_type, or brand kit.
curl --request PATCH \
--url https://api.moda.app/v1/canvases/{canvas_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"description": "<string>",
"brand_kit_id": "bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV"
}
'import requests
url = "https://api.moda.app/v1/canvases/{canvas_id}"
payload = {
"name": "<string>",
"description": "<string>",
"brand_kit_id": "bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
description: '<string>',
brand_kit_id: 'bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV'
})
};
fetch('https://api.moda.app/v1/canvases/{canvas_id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.moda.app/v1/canvases/{canvas_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'description' => '<string>',
'brand_kit_id' => 'bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.moda.app/v1/canvases/{canvas_id}"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"brand_kit_id\": \"bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV\"\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.moda.app/v1/canvases/{canvas_id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"brand_kit_id\": \"bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.moda.app/v1/canvases/{canvas_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"brand_kit_id\": \"bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV\"\n}"
response = http.request(request)
puts response.read_body{
"id": "cvs_01HT9WK8N3M2J4A5Z6P7Q8R9TV",
"name": "<string>",
"url": "<string>",
"category": "<string>",
"visibility": "<string>",
"created_at": "<string>",
"updated_at": "<string>",
"created_by": {
"id": "<string>",
"name": "<string>",
"email": "<string>"
},
"template_type": "<string>",
"brand_kit_id": "<string>"
}{
"type": "invalid_request",
"code": "<string>",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"causes": [
"<unknown>"
],
"details": {},
"retry_after_ms": 123,
"retryable": true
}{
"type": "invalid_request",
"code": "<string>",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"causes": [
"<unknown>"
],
"details": {},
"retry_after_ms": 123,
"retryable": true
}{
"type": "invalid_request",
"code": "<string>",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"causes": [
"<unknown>"
],
"details": {},
"retry_after_ms": 123,
"retryable": true
}{
"type": "invalid_request",
"code": "<string>",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"causes": [
"<unknown>"
],
"details": {},
"retry_after_ms": 123,
"retryable": true
}{
"type": "invalid_request",
"code": "<string>",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"causes": [
"<unknown>"
],
"details": {},
"retry_after_ms": 123,
"retryable": true
}{
"type": "invalid_request",
"code": "<string>",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"causes": [
"<unknown>"
],
"details": {},
"retry_after_ms": 123,
"retryable": true
}{
"type": "invalid_request",
"code": "<string>",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"causes": [
"<unknown>"
],
"details": {},
"retry_after_ms": 123,
"retryable": true
}{
"type": "invalid_request",
"code": "<string>",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"causes": [
"<unknown>"
],
"details": {},
"retry_after_ms": 123,
"retryable": true
}Authorizations
API key from Settings > Developer > REST API
Headers
Calendar-dated API version pin. New integrations should pin 2026-05-01 to opt into the newest response shapes. For back-compat the server also accepts requests with no header and resolves them to the current default (today: 2026-04-12); that default advances on each sunset date. Any unsupported value returns 400 unsupported_version.
2026-04-12, 2026-05-01 "2026-05-01"
Path Parameters
Prefixed cvs_ wire ID (Crockford base32 body) — the canonical, recommended form. For back-compat, a bare UUID string is also accepted in both path parameters and JSON request bodies (older integrations that stored raw UUIDs keep working), as is the prefix over a UUID body (cvs_00000000-0000-4000-8000-000000000000). All three are permanent, supported inputs; only the canonical form is ever emitted.
^cvs_[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$"cvs_01HT9WK8N3M2J4A5Z6P7Q8R9TV"
Body
New display name.
1 - 255New description. Send null to clear.
5000Mark as 'template' (any canvas) or 'theme' (slides canvases only). Send null to clear.
template, theme Prefixed bk_ wire ID (Crockford base32 body) — the canonical, recommended form. For back-compat, a bare UUID string is also accepted in both path parameters and JSON request bodies (older integrations that stored raw UUIDs keep working), as is the prefix over a UUID body (bk_00000000-0000-4000-8000-000000000000). All three are permanent, supported inputs; only the canonical form is ever emitted.
^bk_[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$"bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV"
Response
Successful Response
Unique canvas identifier (prefixed cvs_...).
^cvs_[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$"cvs_01HT9WK8N3M2J4A5Z6P7Q8R9TV"
Display name of the canvas.
Full URL to open the canvas in the Moda editor.
Canvas format category — one of slides, social, carousel, pdf, diagram, ui, animation, prints, web-ads, other, or null when unset. Use this to distinguish slide decks from social posts etc. in list UIs.
Canvas visibility — team (visible to everyone on the team) or private (only the creator and explicit shares).
ISO 8601 timestamp when the canvas was created.
ISO 8601 timestamp of the last modification.
Canvas creator (id, name, email). null when the creator user has been deleted or the relationship failed to load.
Show child attributes
Show child attributes
'template', 'theme', or null.
The canvas's brand kit after the update (bk_...), or null if it is unbound. Always present: the kit just bound when the request set it, otherwise the canvas's current binding as projected into canvas_data — which can briefly lag a bind on a collaboration-active canvas, so a rename issued immediately after a bind may report the pre-bind kit until the collaboration worker projects it.