Skip to content

Connect API — Comments

Comments Overview

The Canva Connect APIs for design comments.

<Warning> The comments APIs are 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.
  • Public integrations that use preview APIs will not pass the review process, and can't be made available to all Canva users. </Warning>

The comments endpoint allows you to create new top-level comments on designs and reply to a top-level comment thread.

Comments APIs

  • Create thread: Create a new comment thread on a design.
  • Create reply: Reply to a comment on a design.
  • Get thread: Get metadata for a comment thread.
  • Get reply: Get a comment reply.
  • List replies: List replies for a comment on a design.
  • <Badge variant="warnLow">deprecated</Badge> Create comment: Create a new comment on a design.
  • <Badge variant="warnLow">deprecated</Badge> Create reply: Reply to a comment on a design.

Create Thread

Create a new comment thread on a design.

<Warning> 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.
  • Public integrations that use preview APIs will not pass the review process, and can't be made available to all Canva users. </Warning>

Creates a new comment thread on a design. For information on comments and how they're used in the Canva UI, see the Canva Help Center.

HTTP method and URL path

POST https://api.canva.com/rest/v1/designs/{designId}/comments

This operation is rate limited to 100 requests per minute for each user of your integration.

Authentication and authorization

This endpoint requires a valid access token that acts on behalf of a user.

Scopes

The access token must have all the following scopes (permissions):

  • comment:write

Header parameters

<Prop.List> <Prop name="Authorization" type="string" required> Provides credentials to authenticate the request, in the form of a Bearer token.

For example: `Authorization: Bearer {token}`

</Prop>

<Prop name="Content-Type" type="string" required> Indicates the media type of the information sent in the request. This must be set to application/json.

For example: `Content-Type: application/json`

</Prop> </Prop.List>

Path parameters

<Prop.List> <Prop name="designId" type="string" required> The design ID. </Prop> </Prop.List>

Body parameters

<Prop.List> <Prop name="message_plaintext" type="string" required> The comment message in plaintext. This is the comment body shown in the Canva UI.

You can also mention users in your message by specifying their User ID and Team ID
using the format `[user_id:team_id]`. If the `assignee_id` parameter is specified, you
must mention the assignee in the message.

&lt;Prop.Extras&gt;
  **Minimum length:** `1`

  **Maximum length:** `2048`
&lt;/Prop.Extras&gt;

</Prop>

<Prop name="assignee_id" type="string"> Lets you assign the comment to a Canva user using their User ID. You must mention the assigned user in the message. </Prop> </Prop.List>

Example request

Examples for using the /v1/designs/{designId}/comments endpoint:

<Tabs storageKey="example.language" disableContentTransition> <Tab name="cURL"> sh curl --request POST 'https://api.canva.com/rest/v1/designs/{designId}/comments' \ --header 'Authorization: Bearer {token}' \ --header 'Content-Type: application/json' \ --data '{ "message_plaintext": "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!", "assignee_id": "oUnPjZ2k2yuhftbWF7873o" }' </Tab>

<Tab name="Node.js"> ```js const fetch = require("node-fetch");

fetch("https://api.canva.com/rest/v1/designs/{designId}/comments", {
  method: "POST",
  headers: {
    "Authorization": "Bearer {token}",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "message_plaintext": "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!",
    "assignee_id": "oUnPjZ2k2yuhftbWF7873o"
  }),
})
  .then(async (response) => {
    const data = await response.json();
    console.log(data);
  })
  .catch(err => console.error(err));
```

</Tab>

<Tab name="Java"> ```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/designs/{designId}/comments"))
            .header("Authorization", "Bearer {token}")
            .header("Content-Type", "application/json")
            .method("POST", HttpRequest.BodyPublishers.ofString("{\"message_plaintext\": \"Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!\", \"assignee_id\": \"oUnPjZ2k2yuhftbWF7873o\"}"))
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient().send(
            request,
            HttpResponse.BodyHandlers.ofString()
        );
        System.out.println(response.body());
    }
}
```

</Tab>

<Tab name="Python"> ```py import requests

headers = {
    "Authorization": "Bearer {token}",
    "Content-Type": "application/json"
}

data = {
    "message_plaintext": "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!",
    "assignee_id": "oUnPjZ2k2yuhftbWF7873o"
}

response = requests.post("https://api.canva.com/rest/v1/designs/{designId}/comments",
    headers=headers,
    json=data
)
print(response.json())
```

</Tab>

<Tab name="C#"> ```csharp using System.Net.Http;

var client = new HttpClient();
var request = new HttpRequestMessage
{
  Method = HttpMethod.Post,
  RequestUri = new Uri("https://api.canva.com/rest/v1/designs/{designId}/comments"),
  Headers =
  {
    { "Authorization", "Bearer {token}" },
  },
  Content = new StringContent(
    "{\"message_plaintext\": \"Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!\", \"assignee_id\": \"oUnPjZ2k2yuhftbWF7873o\"}",
    Encoding.UTF8,
    "application/json"
  ),
};

using (var response = await client.SendAsync(request))
{
  response.EnsureSuccessStatusCode();
  var body = await response.Content.ReadAsStringAsync();
  Console.WriteLine(body);
};
```

</Tab>

<Tab name="Go"> ```go package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	payload := strings.NewReader(`{
	  "message_plaintext": "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!",
	  "assignee_id": "oUnPjZ2k2yuhftbWF7873o"
	}`)

	url := "https://api.canva.com/rest/v1/designs/{designId}/comments"
	req, _ := http.NewRequest("POST", 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))
}
```

</Tab>

<Tab name="PHP"> ```php $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "https://api.canva.com/rest/v1/designs/{designId}/comments", CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => array( 'Authorization: Bearer {token}', 'Content-Type: application/json', ), CURLOPT_POSTFIELDS => json_encode([ "message_plaintext" => "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!", "assignee_id" => "oUnPjZ2k2yuhftbWF7873o" ]) ));

$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);

if (empty($err)) {
  echo $response;
} else {
  echo "Error: " . $err;
}
```

</Tab>

<Tab name="Ruby"> ```ruby require 'net/http' require 'uri'

url = URI('https://api.canva.com/rest/v1/designs/{designId}/comments')
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request['Authorization'] = 'Bearer {token}'
request['Content-Type'] = 'application/json'
request.body = <<REQUEST_BODY
{
  "message_plaintext": "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!",
  "assignee_id": "oUnPjZ2k2yuhftbWF7873o"
}
REQUEST_BODY

response = http.request(request)
puts response.read_body
```

</Tab> </Tabs>

Success response

If successful, the endpoint returns a 200 response with a JSON body with the following parameters:

<Prop.List> <Prop name="thread" type="Thread" required mode="output"> A discussion thread on a design.

The `type` of the thread can be found in the `thread_type` object, along with additional type-specific properties.
The `author` of the thread might be missing if that user account no longer exists.

&lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;thread&lt;/strong&gt;&lt;/&gt;} defaultExpanded={true}&gt;
  &lt;Prop.List&gt;
    &lt;Prop name="id" type="string" required mode="output"&gt;
      The ID of the thread.

      You can use this ID to create replies to the thread using the Create reply API.
    &lt;/Prop&gt;

    &lt;Prop name="design_id" type="string" required mode="output"&gt;
      The ID of the design that the discussion thread is on.
    &lt;/Prop&gt;

    &lt;Prop name="thread_type" type="ThreadType" required mode="output"&gt;
      The type of the discussion thread, along with additional type-specific properties.

      &lt;Tabs&gt;
        &lt;Tab name="comment"&gt;
          A comment thread.

          &lt;Prop.List&gt;
            &lt;Prop name="type" type="string" required mode="output"&gt;
              &lt;Prop.Extras&gt;
                **Available values:** The only valid value is `comment`.
              &lt;/Prop.Extras&gt;
            &lt;/Prop&gt;

            &lt;Prop name="content" type="CommentContent" required mode="output"&gt;
              The content of a comment thread or reply.

              &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;content&lt;/strong&gt;&lt;/&gt;}&gt;
                &lt;Prop.List&gt;
                  &lt;Prop name="plaintext" type="string" required mode="output"&gt;
                    The content in plaintext.
                    Any user mention tags are shown in the format `[user_id:team_id]`.
                  &lt;/Prop&gt;

                  &lt;Prop name="markdown" type="string" mode="output"&gt;
                    The content in markdown.
                    Any user mention tags are shown in the format `[user_id:team_id]`
                  &lt;/Prop&gt;
                &lt;/Prop.List&gt;
              &lt;/PillAccordion&gt;
            &lt;/Prop&gt;

            &lt;Prop name="mentions" type="object" required mode="output"&gt;
              The Canva users mentioned in the comment thread or reply.

              &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;mentions&lt;/strong&gt;&lt;/&gt;}&gt;
                &lt;Prop.List&gt;
                  &lt;Prop name="&lt;KEY&gt;" type="object of UserMentions" mode="output" required required&gt;
                    Information about the user mentioned in a comment thread or reply. Each user mention is keyed using the user's user ID and team ID separated by a colon (`user_id:team_id`).

                    ```json
                    {
                      "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP": {
                        "tag": "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP",
                        "user": {
                          "user_id": "oUnPjZ2k2yuhftbWF7873o",
                          "team_id": "oBpVhLW22VrqtwKgaayRbP",
                          "display_name": "John Doe"
                        }
                      }
                    }
                    ```

                    &lt;Prop.List&gt;
                      &lt;Prop name="tag" type="string" required mode="output"&gt;
                        The mention tag for the user mentioned in the comment thread or reply content. This has the format of the user's user ID and team ID separated by a colon (`user_id:team_id`).
                      &lt;/Prop&gt;

                      &lt;Prop name="user" type="TeamUser" required mode="output"&gt;
                        Metadata for the user, consisting of the User ID, Team ID, and display name.

                        &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;user&lt;/strong&gt;&lt;/&gt;}&gt;
                          &lt;Prop.List&gt;
                            &lt;Prop name="user_id" type="string" mode="output"&gt;
                              The ID of the user.
                            &lt;/Prop&gt;

                            &lt;Prop name="team_id" type="string" mode="output"&gt;
                              The ID of the user's Canva Team.
                            &lt;/Prop&gt;

                            &lt;Prop name="display_name" type="string" mode="output"&gt;
                              The name of the user as shown in the Canva UI.
                            &lt;/Prop&gt;
                          &lt;/Prop.List&gt;
                        &lt;/PillAccordion&gt;
                      &lt;/Prop&gt;
                    &lt;/Prop.List&gt;
                  &lt;/Prop&gt;
                &lt;/Prop.List&gt;
              &lt;/PillAccordion&gt;
            &lt;/Prop&gt;

            &lt;Prop name="assignee" type="User" mode="output"&gt;
              Metadata for the user, consisting of the User ID and display name.

              &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;assignee&lt;/strong&gt;&lt;/&gt;}&gt;
                &lt;Prop.List&gt;
                  &lt;Prop name="id" type="string" required mode="output"&gt;
                    The ID of the user.
                  &lt;/Prop&gt;

                  &lt;Prop name="display_name" type="string" mode="output"&gt;
                    The name of the user as shown in the Canva UI.
                  &lt;/Prop&gt;
                &lt;/Prop.List&gt;
              &lt;/PillAccordion&gt;
            &lt;/Prop&gt;

            &lt;Prop name="resolver" type="User" mode="output"&gt;
              Metadata for the user, consisting of the User ID and display name.

              &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;resolver&lt;/strong&gt;&lt;/&gt;}&gt;
                &lt;Prop.List&gt;
                  &lt;Prop name="id" type="string" required mode="output"&gt;
                    The ID of the user.
                  &lt;/Prop&gt;

                  &lt;Prop name="display_name" type="string" mode="output"&gt;
                    The name of the user as shown in the Canva UI.
                  &lt;/Prop&gt;
                &lt;/Prop.List&gt;
              &lt;/PillAccordion&gt;
            &lt;/Prop&gt;
          &lt;/Prop.List&gt;
        &lt;/Tab&gt;

        &lt;Tab name="suggestion"&gt;
          A suggestion thread.

          &lt;Prop.List&gt;
            &lt;Prop name="type" type="string" required mode="output"&gt;
              &lt;Prop.Extras&gt;
                **Available values:** The only valid value is `suggestion`.
              &lt;/Prop.Extras&gt;
            &lt;/Prop&gt;

            &lt;Prop name="suggested_edits" type="SuggestedEdit[]" required mode="output"&gt;
              The type of the suggested edit, along with additional type-specific properties.

              &lt;Prop.Extras&gt;
                **Minimum items:** `1`
              &lt;/Prop.Extras&gt;

              &lt;Tabs&gt;
                &lt;Tab name="add"&gt;
                  A suggestion to add some text.

                  &lt;Prop.List&gt;
                    &lt;Prop name="type" type="string" required mode="output"&gt;
                      &lt;Prop.Extras&gt;
                        **Available values:** The only valid value is `add`.
                      &lt;/Prop.Extras&gt;
                    &lt;/Prop&gt;
                  &lt;/Prop.List&gt;
                &lt;/Tab&gt;

                &lt;Tab name="delete"&gt;
                  A suggestion to delete some text.

                  &lt;Prop.List&gt;
                    &lt;Prop name="type" type="string" required mode="output"&gt;
                      &lt;Prop.Extras&gt;
                        **Available values:** The only valid value is `delete`.
                      &lt;/Prop.Extras&gt;
                    &lt;/Prop&gt;
                  &lt;/Prop.List&gt;
                &lt;/Tab&gt;

                &lt;Tab name="format"&gt;
                  A suggestion to format some text.

                  &lt;Prop.List&gt;
                    &lt;Prop name="type" type="string" required mode="output"&gt;
                      &lt;Prop.Extras&gt;
                        **Available values:** The only valid value is `format`.
                      &lt;/Prop.Extras&gt;
                    &lt;/Prop&gt;

                    &lt;Prop name="format" type="string" required mode="output"&gt;
                      The suggested format change.

                      &lt;Prop.Extras&gt;
                        **Available values:**

                        * `font_family`
                        * `font_size`
                        * `font_weight`
                        * `font_style`
                        * `color`
                        * `background_color`
                        * `decoration`
                        * `strikethrough`
                        * `link`
                        * `letter_spacing`
                        * `line_height`
                        * `direction`
                        * `text_align`
                        * `list_marker`
                        * `list_level`
                        * `margin_inline_start`
                        * `text_indent`
                        * `font_size_modifier`
                        * `vertical_align`
                      &lt;/Prop.Extras&gt;
                    &lt;/Prop&gt;
                  &lt;/Prop.List&gt;
                &lt;/Tab&gt;
              &lt;/Tabs&gt;
            &lt;/Prop&gt;

            &lt;Prop name="status" type="string" required mode="output"&gt;
              The current status of the suggestion.

              &lt;Prop.Extras&gt;
                **Available values:**

                * `open`: A suggestion was made, but it hasn't been accepted or rejected yet.
                * `accepted`: A suggestion was accepted and applied to the design.
                * `rejected`: A suggestion was rejected and not applied to the design.
              &lt;/Prop.Extras&gt;
            &lt;/Prop&gt;
          &lt;/Prop.List&gt;
        &lt;/Tab&gt;
      &lt;/Tabs&gt;
    &lt;/Prop&gt;

    &lt;Prop name="created_at" type="integer" required mode="output"&gt;
      When the thread was created, as a Unix timestamp
      (in seconds since the Unix Epoch).
    &lt;/Prop&gt;

    &lt;Prop name="updated_at" type="integer" required mode="output"&gt;
      When the thread was last updated, as a Unix timestamp
      (in seconds since the Unix Epoch).
    &lt;/Prop&gt;

    &lt;Prop name="author" type="User" mode="output"&gt;
      Metadata for the user, consisting of the User ID and display name.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;author&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="id" type="string" required mode="output"&gt;
            The ID of the user.
          &lt;/Prop&gt;

          &lt;Prop name="display_name" type="string" mode="output"&gt;
            The name of the user as shown in the Canva UI.
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;
  &lt;/Prop.List&gt;
&lt;/PillAccordion&gt;

</Prop> </Prop.List>

Example response

json
{
  "thread": {
    "id": "KeAbiEAjZEj",
    "design_id": "DAFVztcvd9z",
    "thread_type": {
      "type": "comment",
      "content": {
        "plaintext": "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!",
        "markdown": "*_Great work_* [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!"
      },
      "mentions": {
        "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP": {
          "tag": "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP",
          "user": {
            "user_id": "oUnPjZ2k2yuhftbWF7873o",
            "team_id": "oBpVhLW22VrqtwKgaayRbP",
            "display_name": "John Doe"
          }
        }
      },
      "assignee": {
        "id": "uKakKUfI03Fg8k2gZ6OkT",
        "display_name": "John Doe"
      },
      "resolver": {
        "id": "uKakKUfI03Fg8k2gZ6OkT",
        "display_name": "John Doe"
      }
    },
    "author": {
      "id": "uKakKUfI03Fg8k2gZ6OkT",
      "display_name": "John Doe"
    },
    "created_at": 1692928800,
    "updated_at": 1692928900
  }
}

Error responses

400 Bad Request

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "bad_request_body",
  "message": "Assignee must be mentioned in comment content"
}

403 Forbidden

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "too_many_comments",
  "message": "Design already has the maximum number of allowed comments"
}

404 Not Found

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "design_not_found",
  "message": "Design not found"
}

Create Comment

Create a new comment on a design.

<Warning> This API is deprecated, so you should use the Create thread API instead. </Warning>

<Warning> 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.
  • Public integrations that use preview APIs will not pass the review process, and can't be made available to all Canva users. </Warning>

Create a new top-level comment on a design. For information on comments and how they're used in the Canva UI, see the Canva Help Center. A design can have a maximum of 1000 comments.

HTTP method and URL path

POST https://api.canva.com/rest/v1/comments

This operation is rate limited to 20 requests per minute for each user of your integration.

Authentication and authorization

This endpoint requires a valid access token that acts on behalf of a user.

Scopes

The access token must have all the following scopes (permissions):

  • comment:write

Header parameters

<Prop.List> <Prop name="Authorization" type="string" required> Provides credentials to authenticate the request, in the form of a Bearer token.

For example: `Authorization: Bearer {token}`

</Prop>

<Prop name="Content-Type" type="string" required> Indicates the media type of the information sent in the request. This must be set to application/json.

For example: `Content-Type: application/json`

</Prop> </Prop.List>

Body parameters

<Prop.List> <Prop name="attached_to" type="CommentObjectInput" required> An object containing identifying information for the design or other object you want to attach the comment to.

&lt;Tabs&gt;
  &lt;Tab name="design"&gt;
    If the comment is attached to a Canva Design.

    &lt;Prop.List&gt;
      &lt;Prop name="type" type="string" required&gt;
        &lt;Prop.Extras&gt;
          **Available values:** The only valid value is `design`.
        &lt;/Prop.Extras&gt;
      &lt;/Prop&gt;

      &lt;Prop name="design_id" type="string" required&gt;
        The ID of the design you want to attach this comment to.
      &lt;/Prop&gt;
    &lt;/Prop.List&gt;
  &lt;/Tab&gt;
&lt;/Tabs&gt;

</Prop>

<Prop name="message" type="string" required> The comment message. This is the comment body shown in the Canva UI.

You can also mention users in your message by specifying their User ID and Team ID
using the format `[user_id:team_id]`. If the `assignee_id` parameter is specified, you
must mention the assignee in the message.

&lt;Prop.Extras&gt;
  **Minimum length:** `1`

  **Maximum length:** `2048`
&lt;/Prop.Extras&gt;

</Prop>

<Prop name="assignee_id" type="string" deprecated> Lets you assign the comment to a Canva user using their User ID. You must mention the assigned user in the message. </Prop> </Prop.List>

Example request

Examples for using the /v1/comments endpoint:

<Tabs storageKey="example.language" disableContentTransition> <Tab name="cURL"> sh curl --request POST 'https://api.canva.com/rest/v1/comments' \ --header 'Authorization: Bearer {token}' \ --header 'Content-Type: application/json' \ --data '{ "attached_to": { "design_id": "DAFVztcvd9z", "type": "design" }, "message": "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!", "assignee_id": "oUnPjZ2k2yuhftbWF7873o" }' </Tab>

<Tab name="Node.js"> ```js const fetch = require("node-fetch");

fetch("https://api.canva.com/rest/v1/comments", {
  method: "POST",
  headers: {
    "Authorization": "Bearer {token}",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "attached_to": {
      "design_id": "DAFVztcvd9z",
      "type": "design"
    },
    "message": "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!",
    "assignee_id": "oUnPjZ2k2yuhftbWF7873o"
  }),
})
  .then(async (response) => {
    const data = await response.json();
    console.log(data);
  })
  .catch(err => console.error(err));
```

</Tab>

<Tab name="Java"> ```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/comments"))
            .header("Authorization", "Bearer {token}")
            .header("Content-Type", "application/json")
            .method("POST", HttpRequest.BodyPublishers.ofString("{\"attached_to\": {\"design_id\": \"DAFVztcvd9z\", \"type\": \"design\"}, \"message\": \"Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!\", \"assignee_id\": \"oUnPjZ2k2yuhftbWF7873o\"}"))
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient().send(
            request,
            HttpResponse.BodyHandlers.ofString()
        );
        System.out.println(response.body());
    }
}
```

</Tab>

<Tab name="Python"> ```py import requests

headers = {
    "Authorization": "Bearer {token}",
    "Content-Type": "application/json"
}

data = {
    "attached_to": {
        "design_id": "DAFVztcvd9z",
        "type": "design"
    },
    "message": "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!",
    "assignee_id": "oUnPjZ2k2yuhftbWF7873o"
}

response = requests.post("https://api.canva.com/rest/v1/comments",
    headers=headers,
    json=data
)
print(response.json())
```

</Tab>

<Tab name="C#"> ```csharp using System.Net.Http;

var client = new HttpClient();
var request = new HttpRequestMessage
{
  Method = HttpMethod.Post,
  RequestUri = new Uri("https://api.canva.com/rest/v1/comments"),
  Headers =
  {
    { "Authorization", "Bearer {token}" },
  },
  Content = new StringContent(
    "{\"attached_to\": {\"design_id\": \"DAFVztcvd9z\", \"type\": \"design\"}, \"message\": \"Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!\", \"assignee_id\": \"oUnPjZ2k2yuhftbWF7873o\"}",
    Encoding.UTF8,
    "application/json"
  ),
};

using (var response = await client.SendAsync(request))
{
  response.EnsureSuccessStatusCode();
  var body = await response.Content.ReadAsStringAsync();
  Console.WriteLine(body);
};
```

</Tab>

<Tab name="Go"> ```go package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	payload := strings.NewReader(`{
	  "attached_to": {
	    "design_id": "DAFVztcvd9z",
	    "type": "design"
	  },
	  "message": "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!",
	  "assignee_id": "oUnPjZ2k2yuhftbWF7873o"
	}`)

	url := "https://api.canva.com/rest/v1/comments"
	req, _ := http.NewRequest("POST", 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))
}
```

</Tab>

<Tab name="PHP"> ```php $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "https://api.canva.com/rest/v1/comments", CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => array( 'Authorization: Bearer {token}', 'Content-Type: application/json', ), CURLOPT_POSTFIELDS => json_encode([ "attached_to" => [ "design_id" => "DAFVztcvd9z", "type" => "design" ], "message" => "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!", "assignee_id" => "oUnPjZ2k2yuhftbWF7873o" ]) ));

$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);

if (empty($err)) {
  echo $response;
} else {
  echo "Error: " . $err;
}
```

</Tab>

<Tab name="Ruby"> ```ruby require 'net/http' require 'uri'

url = URI('https://api.canva.com/rest/v1/comments')
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request['Authorization'] = 'Bearer {token}'
request['Content-Type'] = 'application/json'
request.body = <<REQUEST_BODY
{
  "attached_to": {
    "design_id": "DAFVztcvd9z",
    "type": "design"
  },
  "message": "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!",
  "assignee_id": "oUnPjZ2k2yuhftbWF7873o"
}
REQUEST_BODY

response = http.request(request)
puts response.read_body
```

</Tab> </Tabs>

Success response

If successful, the endpoint returns a 200 response with a JSON body with the following parameters:

<Prop.List> <Prop name="comment" type="ParentComment" required mode="output"> Data about the comment, including the message, author, and the object (such as a design) the comment is attached to.

&lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;comment&lt;/strong&gt;&lt;/&gt;} defaultExpanded={true}&gt;
  &lt;Prop.List&gt;
    &lt;Prop name="type" type="string" required mode="output"&gt;
      The type of comment. When creating a new parent (top-level)
      comment, the `type` is `parent`.

      &lt;Prop.Extras&gt;
        **Available values:** The only valid value is `parent`.
      &lt;/Prop.Extras&gt;
    &lt;/Prop&gt;

    &lt;Prop name="id" type="string" required mode="output"&gt;
      The ID of the comment.

      You can use this ID to create replies to the comment using the Create reply API.
    &lt;/Prop&gt;

    &lt;Prop name="message" type="string" required mode="output"&gt;
      The comment message. This is the comment body shown in the Canva UI.
      User mentions are shown here in the format `[user_id:team_id]`.
    &lt;/Prop&gt;

    &lt;Prop name="author" type="User" required mode="output"&gt;
      Metadata for the user, consisting of the User ID and display name.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;author&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="id" type="string" required mode="output"&gt;
            The ID of the user.
          &lt;/Prop&gt;

          &lt;Prop name="display_name" type="string" deprecated mode="output"&gt;
            The name of the user as shown in the Canva UI.
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;

    &lt;Prop name="created_at" type="integer" deprecated mode="output"&gt;
      When the comment or reply was created, as a Unix timestamp
      (in seconds since the Unix Epoch).
    &lt;/Prop&gt;

    &lt;Prop name="updated_at" type="integer" deprecated mode="output"&gt;
      When the comment or reply was last updated, as a Unix timestamp
      (in seconds since the Unix Epoch).
    &lt;/Prop&gt;

    &lt;Prop name="assignee" type="User" deprecated mode="output"&gt;
      Metadata for the user, consisting of the User ID and display name.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;assignee&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="id" type="string" required mode="output"&gt;
            The ID of the user.
          &lt;/Prop&gt;

          &lt;Prop name="display_name" type="string" deprecated mode="output"&gt;
            The name of the user as shown in the Canva UI.
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;

    &lt;Prop name="resolver" type="User" deprecated mode="output"&gt;
      Metadata for the user, consisting of the User ID and display name.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;resolver&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="id" type="string" required mode="output"&gt;
            The ID of the user.
          &lt;/Prop&gt;

          &lt;Prop name="display_name" type="string" deprecated mode="output"&gt;
            The name of the user as shown in the Canva UI.
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;

    &lt;Prop name="mentions" type="object" required mode="output"&gt;
      The Canva users mentioned in the comment.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;mentions&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="&lt;KEY&gt;" type="object of TeamUsers" mode="output" required&gt;
            Metadata for the user, consisting of the User ID, Team ID, and display name.

            &lt;Prop.List&gt;
              &lt;Prop name="user_id" type="string" deprecated mode="output"&gt;
                The ID of the user.
              &lt;/Prop&gt;

              &lt;Prop name="team_id" type="string" deprecated mode="output"&gt;
                The ID of the user's Canva Team.
              &lt;/Prop&gt;

              &lt;Prop name="display_name" type="string" deprecated mode="output"&gt;
                The name of the user as shown in the Canva UI.
              &lt;/Prop&gt;
            &lt;/Prop.List&gt;
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;

    &lt;Prop name="attached_to" type="CommentObject" deprecated mode="output"&gt;
      Identifying information about the object (such as a design) that the comment is attached to.

      &lt;Tabs&gt;
        &lt;Tab name="design"&gt;
          If the comment is attached to a Canva Design.

          &lt;Prop.List&gt;
            &lt;Prop name="type" type="string" required mode="output"&gt;
              &lt;Prop.Extras&gt;
                **Available values:** The only valid value is `design`.
              &lt;/Prop.Extras&gt;
            &lt;/Prop&gt;

            &lt;Prop name="design_id" type="string" required mode="output"&gt;
              The ID of the design this comment is attached to.
            &lt;/Prop&gt;
          &lt;/Prop.List&gt;
        &lt;/Tab&gt;
      &lt;/Tabs&gt;
    &lt;/Prop&gt;
  &lt;/Prop.List&gt;
&lt;/PillAccordion&gt;

</Prop> </Prop.List>

Example response

json
{}

Error responses

400 Bad Request

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "bad_request_body",
  "message": "Assignee must be mentioned in comment content"
}

403 Forbidden

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "too_many_comments",
  "message": "Design already has the maximum number of allowed comments"
}

404 Not Found

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "design_not_found",
  "message": "Design not found"
}

Create Reply

Reply to a comment on a design.

<Warning> 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.
  • Public integrations that use preview APIs will not pass the review process, and can't be made available to all Canva users. </Warning>

Creates a reply to a comment or suggestion thread on a design. To reply to an existing thread, you must provide the ID of the thread which is returned when a thread is created, or from the thread_id value of an existing reply in the thread. Each thread can have a maximum of 100 replies created for it.

For information on comments and how they're used in the Canva UI, see the Canva Help Center.

HTTP method and URL path

POST https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies

This operation is rate limited to 20 requests per minute for each user of your integration.

Authentication and authorization

This endpoint requires a valid access token that acts on behalf of a user.

Scopes

The access token must have all the following scopes (permissions):

  • comment:write

Header parameters

<Prop.List> <Prop name="Authorization" type="string" required> Provides credentials to authenticate the request, in the form of a Bearer token.

For example: `Authorization: Bearer {token}`

</Prop>

<Prop name="Content-Type" type="string" required> Indicates the media type of the information sent in the request. This must be set to application/json.

For example: `Content-Type: application/json`

</Prop> </Prop.List>

Path parameters

<Prop.List> <Prop name="designId" type="string" required> The design ID. </Prop>

<Prop name="threadId" type="string" required> The ID of the thread. </Prop> </Prop.List>

Body parameters

<Prop.List> <Prop name="message_plaintext" type="string" required> The comment message of the reply in plaintext. This is the reply comment shown in the Canva UI.

You can also mention users in your message by specifying their User ID and Team ID
using the format `[user_id:team_id]`.

&lt;Prop.Extras&gt;
  **Minimum length:** `1`

  **Maximum length:** `2048`
&lt;/Prop.Extras&gt;

</Prop> </Prop.List>

Example request

Examples for using the /v1/designs/{designId}/comments/{threadId}/replies endpoint:

<Tabs storageKey="example.language" disableContentTransition> <Tab name="cURL"> sh curl --request POST 'https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies' \ --header 'Authorization: Bearer {token}' \ --header 'Content-Type: application/json' \ --data '{ "message_plaintext": "Thanks!" }' </Tab>

<Tab name="Node.js"> ```js const fetch = require("node-fetch");

fetch("https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies", {
  method: "POST",
  headers: {
    "Authorization": "Bearer {token}",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "message_plaintext": "Thanks!"
  }),
})
  .then(async (response) => {
    const data = await response.json();
    console.log(data);
  })
  .catch(err => console.error(err));
```

</Tab>

<Tab name="Java"> ```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/designs/{designId}/comments/{threadId}/replies"))
            .header("Authorization", "Bearer {token}")
            .header("Content-Type", "application/json")
            .method("POST", HttpRequest.BodyPublishers.ofString("{\"message_plaintext\": \"Thanks!\"}"))
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient().send(
            request,
            HttpResponse.BodyHandlers.ofString()
        );
        System.out.println(response.body());
    }
}
```

</Tab>

<Tab name="Python"> ```py import requests

headers = {
    "Authorization": "Bearer {token}",
    "Content-Type": "application/json"
}

data = {
    "message_plaintext": "Thanks!"
}

response = requests.post("https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies",
    headers=headers,
    json=data
)
print(response.json())
```

</Tab>

<Tab name="C#"> ```csharp using System.Net.Http;

var client = new HttpClient();
var request = new HttpRequestMessage
{
  Method = HttpMethod.Post,
  RequestUri = new Uri("https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies"),
  Headers =
  {
    { "Authorization", "Bearer {token}" },
  },
  Content = new StringContent(
    "{\"message_plaintext\": \"Thanks!\"}",
    Encoding.UTF8,
    "application/json"
  ),
};

using (var response = await client.SendAsync(request))
{
  response.EnsureSuccessStatusCode();
  var body = await response.Content.ReadAsStringAsync();
  Console.WriteLine(body);
};
```

</Tab>

<Tab name="Go"> ```go package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	payload := strings.NewReader(`{
	  "message_plaintext": "Thanks!"
	}`)

	url := "https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies"
	req, _ := http.NewRequest("POST", 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))
}
```

</Tab>

<Tab name="PHP"> ```php $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies", CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => array( 'Authorization: Bearer {token}', 'Content-Type: application/json', ), CURLOPT_POSTFIELDS => json_encode([ "message_plaintext" => "Thanks!" ]) ));

$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);

if (empty($err)) {
  echo $response;
} else {
  echo "Error: " . $err;
}
```

</Tab>

<Tab name="Ruby"> ```ruby require 'net/http' require 'uri'

url = URI('https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies')
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request['Authorization'] = 'Bearer {token}'
request['Content-Type'] = 'application/json'
request.body = <<REQUEST_BODY
{
  "message_plaintext": "Thanks!"
}
REQUEST_BODY

response = http.request(request)
puts response.read_body
```

</Tab> </Tabs>

Success response

If successful, the endpoint returns a 200 response with a JSON body with the following parameters:

<Prop.List> <Prop name="reply" type="Reply" required mode="output"> A reply to a thread.

The `author` of the reply might be missing if that user account no longer exists.

&lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;reply&lt;/strong&gt;&lt;/&gt;} defaultExpanded={true}&gt;
  &lt;Prop.List&gt;
    &lt;Prop name="id" type="string" required mode="output"&gt;
      The ID of the reply.
    &lt;/Prop&gt;

    &lt;Prop name="design_id" type="string" required mode="output"&gt;
      The ID of the design that the thread for this reply is attached to.
    &lt;/Prop&gt;

    &lt;Prop name="thread_id" type="string" required mode="output"&gt;
      The ID of the thread this reply is in.
    &lt;/Prop&gt;

    &lt;Prop name="content" type="CommentContent" required mode="output"&gt;
      The content of a comment thread or reply.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;content&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="plaintext" type="string" required mode="output"&gt;
            The content in plaintext.
            Any user mention tags are shown in the format `[user_id:team_id]`.
          &lt;/Prop&gt;

          &lt;Prop name="markdown" type="string" mode="output"&gt;
            The content in markdown.
            Any user mention tags are shown in the format `[user_id:team_id]`
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;

    &lt;Prop name="mentions" type="object" required mode="output"&gt;
      The Canva users mentioned in the comment thread or reply.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;mentions&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="&lt;KEY&gt;" type="object of UserMentions" mode="output" required required&gt;
            Information about the user mentioned in a comment thread or reply. Each user mention is keyed using the user's user ID and team ID separated by a colon (`user_id:team_id`).

            ```json
            {
              "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP": {
                "tag": "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP",
                "user": {
                  "user_id": "oUnPjZ2k2yuhftbWF7873o",
                  "team_id": "oBpVhLW22VrqtwKgaayRbP",
                  "display_name": "John Doe"
                }
              }
            }
            ```

            &lt;Prop.List&gt;
              &lt;Prop name="tag" type="string" required mode="output"&gt;
                The mention tag for the user mentioned in the comment thread or reply content. This has the format of the user's user ID and team ID separated by a colon (`user_id:team_id`).
              &lt;/Prop&gt;

              &lt;Prop name="user" type="TeamUser" required mode="output"&gt;
                Metadata for the user, consisting of the User ID, Team ID, and display name.

                &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;user&lt;/strong&gt;&lt;/&gt;}&gt;
                  &lt;Prop.List&gt;
                    &lt;Prop name="user_id" type="string" mode="output"&gt;
                      The ID of the user.
                    &lt;/Prop&gt;

                    &lt;Prop name="team_id" type="string" mode="output"&gt;
                      The ID of the user's Canva Team.
                    &lt;/Prop&gt;

                    &lt;Prop name="display_name" type="string" mode="output"&gt;
                      The name of the user as shown in the Canva UI.
                    &lt;/Prop&gt;
                  &lt;/Prop.List&gt;
                &lt;/PillAccordion&gt;
              &lt;/Prop&gt;
            &lt;/Prop.List&gt;
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;

    &lt;Prop name="created_at" type="integer" required mode="output"&gt;
      When the reply was created, as a Unix timestamp
      (in seconds since the Unix Epoch).
    &lt;/Prop&gt;

    &lt;Prop name="updated_at" type="integer" required mode="output"&gt;
      When the reply was last updated, as a Unix timestamp
      (in seconds since the Unix Epoch).
    &lt;/Prop&gt;

    &lt;Prop name="author" type="User" mode="output"&gt;
      Metadata for the user, consisting of the User ID and display name.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;author&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="id" type="string" required mode="output"&gt;
            The ID of the user.
          &lt;/Prop&gt;

          &lt;Prop name="display_name" type="string" mode="output"&gt;
            The name of the user as shown in the Canva UI.
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;
  &lt;/Prop.List&gt;
&lt;/PillAccordion&gt;

</Prop> </Prop.List>

Example response

json
{
  "reply": {
    "id": "KeAZEAjijEb",
    "design_id": "DAFVztcvd9z",
    "thread_id": "KeAbiEAjZEj",
    "author": {
      "id": "uKakKUfI03Fg8k2gZ6OkT",
      "display_name": "John Doe"
    },
    "content": {
      "plaintext": "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!",
      "markdown": "*_Great work_* [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!"
    },
    "mentions": {
      "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP": {
        "tag": "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP",
        "user": {
          "user_id": "oUnPjZ2k2yuhftbWF7873o",
          "team_id": "oBpVhLW22VrqtwKgaayRbP",
          "display_name": "John Doe"
        }
      }
    },
    "created_at": 1692929800,
    "updated_at": 1692929900
  }
}

Error responses

400 Bad Request

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "message_too_long",
  "message": "Message is too long"
}

403 Forbidden

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "too_many_replies",
  "message": "This comment thread already has the maximum number of allowed replies"
}

404 Not Found

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "design_not_found",
  "message": "Design or comment not found"
}

Create Reply (Deprecated)

Reply to a comment on a design.

<Warning> This API is deprecated, so you should use the Create reply API instead. </Warning>

<Warning> 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.
  • Public integrations that use preview APIs will not pass the review process, and can't be made available to all Canva users. </Warning>

Creates a reply to a comment in a design. To reply to an existing thread of comments, you can use either the id of the parent (original) comment, or the thread_id of a comment in the thread. Each comment can have a maximum of 100 replies created for it.

For information on comments and how they're used in the Canva UI, see the Canva Help Center.

HTTP method and URL path

POST https://api.canva.com/rest/v1/comments/{commentId}/replies

This operation is rate limited to 20 requests per minute for each user of your integration.

Authentication and authorization

This endpoint requires a valid access token that acts on behalf of a user.

Scopes

The access token must have all the following scopes (permissions):

  • comment:write

Header parameters

<Prop.List> <Prop name="Authorization" type="string" required> Provides credentials to authenticate the request, in the form of a Bearer token.

For example: `Authorization: Bearer {token}`

</Prop>

<Prop name="Content-Type" type="string" required> Indicates the media type of the information sent in the request. This must be set to application/json.

For example: `Content-Type: application/json`

</Prop> </Prop.List>

Path parameters

<Prop.List> <Prop name="commentId" type="string" required> The ID of the comment. </Prop> </Prop.List>

Body parameters

<Prop.List> <Prop name="attached_to" type="CommentObjectInput" required> An object containing identifying information for the design or other object you want to attach the comment to.

&lt;Tabs&gt;
  &lt;Tab name="design"&gt;
    If the comment is attached to a Canva Design.

    &lt;Prop.List&gt;
      &lt;Prop name="type" type="string" required&gt;
        &lt;Prop.Extras&gt;
          **Available values:** The only valid value is `design`.
        &lt;/Prop.Extras&gt;
      &lt;/Prop&gt;

      &lt;Prop name="design_id" type="string" required&gt;
        The ID of the design you want to attach this comment to.
      &lt;/Prop&gt;
    &lt;/Prop.List&gt;
  &lt;/Tab&gt;
&lt;/Tabs&gt;

</Prop>

<Prop name="message" type="string" required> The reply comment message. This is the reply comment body shown in the Canva UI.

You can also mention users in your message by specifying their User ID and Team ID
using the format `[user_id:team_id]`.

&lt;Prop.Extras&gt;
  **Minimum length:** `1`

  **Maximum length:** `2048`
&lt;/Prop.Extras&gt;

</Prop> </Prop.List>

Example request

Examples for using the /v1/comments/{commentId}/replies endpoint:

<Tabs storageKey="example.language" disableContentTransition> <Tab name="cURL"> sh curl --request POST 'https://api.canva.com/rest/v1/comments/{commentId}/replies' \ --header 'Authorization: Bearer {token}' \ --header 'Content-Type: application/json' \ --data '{ "attached_to": { "design_id": "DAFVztcvd9z", "type": "design" }, "message": "Thanks!" }' </Tab>

<Tab name="Node.js"> ```js const fetch = require("node-fetch");

fetch("https://api.canva.com/rest/v1/comments/{commentId}/replies", {
  method: "POST",
  headers: {
    "Authorization": "Bearer {token}",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "attached_to": {
      "design_id": "DAFVztcvd9z",
      "type": "design"
    },
    "message": "Thanks!"
  }),
})
  .then(async (response) => {
    const data = await response.json();
    console.log(data);
  })
  .catch(err => console.error(err));
```

</Tab>

<Tab name="Java"> ```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/comments/{commentId}/replies"))
            .header("Authorization", "Bearer {token}")
            .header("Content-Type", "application/json")
            .method("POST", HttpRequest.BodyPublishers.ofString("{\"attached_to\": {\"design_id\": \"DAFVztcvd9z\", \"type\": \"design\"}, \"message\": \"Thanks!\"}"))
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient().send(
            request,
            HttpResponse.BodyHandlers.ofString()
        );
        System.out.println(response.body());
    }
}
```

</Tab>

<Tab name="Python"> ```py import requests

headers = {
    "Authorization": "Bearer {token}",
    "Content-Type": "application/json"
}

data = {
    "attached_to": {
        "design_id": "DAFVztcvd9z",
        "type": "design"
    },
    "message": "Thanks!"
}

response = requests.post("https://api.canva.com/rest/v1/comments/{commentId}/replies",
    headers=headers,
    json=data
)
print(response.json())
```

</Tab>

<Tab name="C#"> ```csharp using System.Net.Http;

var client = new HttpClient();
var request = new HttpRequestMessage
{
  Method = HttpMethod.Post,
  RequestUri = new Uri("https://api.canva.com/rest/v1/comments/{commentId}/replies"),
  Headers =
  {
    { "Authorization", "Bearer {token}" },
  },
  Content = new StringContent(
    "{\"attached_to\": {\"design_id\": \"DAFVztcvd9z\", \"type\": \"design\"}, \"message\": \"Thanks!\"}",
    Encoding.UTF8,
    "application/json"
  ),
};

using (var response = await client.SendAsync(request))
{
  response.EnsureSuccessStatusCode();
  var body = await response.Content.ReadAsStringAsync();
  Console.WriteLine(body);
};
```

</Tab>

<Tab name="Go"> ```go package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	payload := strings.NewReader(`{
	  "attached_to": {
	    "design_id": "DAFVztcvd9z",
	    "type": "design"
	  },
	  "message": "Thanks!"
	}`)

	url := "https://api.canva.com/rest/v1/comments/{commentId}/replies"
	req, _ := http.NewRequest("POST", 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))
}
```

</Tab>

<Tab name="PHP"> ```php $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "https://api.canva.com/rest/v1/comments/{commentId}/replies", CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => array( 'Authorization: Bearer {token}', 'Content-Type: application/json', ), CURLOPT_POSTFIELDS => json_encode([ "attached_to" => [ "design_id" => "DAFVztcvd9z", "type" => "design" ], "message" => "Thanks!" ]) ));

$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);

if (empty($err)) {
  echo $response;
} else {
  echo "Error: " . $err;
}
```

</Tab>

<Tab name="Ruby"> ```ruby require 'net/http' require 'uri'

url = URI('https://api.canva.com/rest/v1/comments/{commentId}/replies')
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request['Authorization'] = 'Bearer {token}'
request['Content-Type'] = 'application/json'
request.body = <<REQUEST_BODY
{
  "attached_to": {
    "design_id": "DAFVztcvd9z",
    "type": "design"
  },
  "message": "Thanks!"
}
REQUEST_BODY

response = http.request(request)
puts response.read_body
```

</Tab> </Tabs>

Success response

If successful, the endpoint returns a 200 response with a JSON body with the following parameters:

<Prop.List> <Prop name="comment" type="ReplyComment" required mode="output"> Data about the reply comment, including the message, author, and the object (such as a design) the comment is attached to.

&lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;comment&lt;/strong&gt;&lt;/&gt;} defaultExpanded={true}&gt;
  &lt;Prop.List&gt;
    &lt;Prop name="type" type="string" required mode="output"&gt;
      The type of comment. When creating a reply to a top-level
      comment, the `type` is `reply`.

      &lt;Prop.Extras&gt;
        **Available values:** The only valid value is `reply`.
      &lt;/Prop.Extras&gt;
    &lt;/Prop&gt;

    &lt;Prop name="id" type="string" required mode="output"&gt;
      The ID of the comment.
    &lt;/Prop&gt;

    &lt;Prop name="message" type="string" required mode="output"&gt;
      The comment message. This is the comment body shown in the Canva UI.
      User mentions are shown here in the format `[user_id:team_id]`.
    &lt;/Prop&gt;

    &lt;Prop name="author" type="User" required mode="output"&gt;
      Metadata for the user, consisting of the User ID and display name.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;author&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="id" type="string" required mode="output"&gt;
            The ID of the user.
          &lt;/Prop&gt;

          &lt;Prop name="display_name" type="string" deprecated mode="output"&gt;
            The name of the user as shown in the Canva UI.
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;

    &lt;Prop name="thread_id" type="string" required mode="output"&gt;
      The ID of the comment thread this reply is in. This ID is the same as the `id` of the
      parent comment.
    &lt;/Prop&gt;

    &lt;Prop name="created_at" type="integer" deprecated mode="output"&gt;
      When the comment or reply was created, as a Unix timestamp
      (in seconds since the Unix Epoch).
    &lt;/Prop&gt;

    &lt;Prop name="updated_at" type="integer" deprecated mode="output"&gt;
      When the comment or reply was last updated, as a Unix timestamp
      (in seconds since the Unix Epoch).
    &lt;/Prop&gt;

    &lt;Prop name="mentions" type="object" required mode="output"&gt;
      The Canva users mentioned in the comment.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;mentions&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="&lt;KEY&gt;" type="object of TeamUsers" mode="output" required&gt;
            Metadata for the user, consisting of the User ID, Team ID, and display name.

            &lt;Prop.List&gt;
              &lt;Prop name="user_id" type="string" deprecated mode="output"&gt;
                The ID of the user.
              &lt;/Prop&gt;

              &lt;Prop name="team_id" type="string" deprecated mode="output"&gt;
                The ID of the user's Canva Team.
              &lt;/Prop&gt;

              &lt;Prop name="display_name" type="string" deprecated mode="output"&gt;
                The name of the user as shown in the Canva UI.
              &lt;/Prop&gt;
            &lt;/Prop.List&gt;
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;

    &lt;Prop name="attached_to" type="CommentObject" deprecated mode="output"&gt;
      Identifying information about the object (such as a design) that the comment is attached to.

      &lt;Tabs&gt;
        &lt;Tab name="design"&gt;
          If the comment is attached to a Canva Design.

          &lt;Prop.List&gt;
            &lt;Prop name="type" type="string" required mode="output"&gt;
              &lt;Prop.Extras&gt;
                **Available values:** The only valid value is `design`.
              &lt;/Prop.Extras&gt;
            &lt;/Prop&gt;

            &lt;Prop name="design_id" type="string" required mode="output"&gt;
              The ID of the design this comment is attached to.
            &lt;/Prop&gt;
          &lt;/Prop.List&gt;
        &lt;/Tab&gt;
      &lt;/Tabs&gt;
    &lt;/Prop&gt;
  &lt;/Prop.List&gt;
&lt;/PillAccordion&gt;

</Prop> </Prop.List>

Example response

json
{}

Error responses

400 Bad Request

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "message_too_long",
  "message": "Message is too long"
}

403 Forbidden

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "too_many_replies",
  "message": "This comment thread already has the maximum number of allowed replies"
}

404 Not Found

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "design_not_found",
  "message": "Design or comment not found"
}

Get Thread

Get metadata for a comment thread.

<Warning> 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.
  • Public integrations that use preview APIs will not pass the review process, and can't be made available to all Canva users. </Warning>

Gets a comment or suggestion thread on a design. To retrieve a reply to a comment thread, use the Get reply API. For information on comments and how they're used in the Canva UI, see the Canva Help Center.

HTTP method and URL path

GET https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}

This operation is rate limited to 100 requests per minute for each user of your integration.

Authentication and authorization

This endpoint requires a valid access token that acts on behalf of a user.

Scopes

The access token must have all the following scopes (permissions):

  • comment:read

Header parameters

<Prop.List> <Prop name="Authorization" type="string" required> Provides credentials to authenticate the request, in the form of a Bearer token.

For example: `Authorization: Bearer {token}`

</Prop> </Prop.List>

Path parameters

<Prop.List> <Prop name="designId" type="string" required> The design ID. </Prop>

<Prop name="threadId" type="string" required> The ID of the thread. </Prop> </Prop.List>

Example request

Examples for using the /v1/designs/{designId}/comments/{threadId} endpoint:

<Tabs storageKey="example.language" disableContentTransition> <Tab name="cURL"> sh curl --request GET 'https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}' \ --header 'Authorization: Bearer {token}' </Tab>

<Tab name="Node.js"> ```js const fetch = require("node-fetch");

fetch("https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}", {
  method: "GET",
  headers: {
    "Authorization": "Bearer {token}",
  },
})
  .then(async (response) => {
    const data = await response.json();
    console.log(data);
  })
  .catch(err => console.error(err));
```

</Tab>

<Tab name="Java"> ```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/designs/{designId}/comments/{threadId}"))
            .header("Authorization", "Bearer {token}")
            .method("GET", HttpRequest.BodyPublishers.noBody())
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient().send(
            request,
            HttpResponse.BodyHandlers.ofString()
        );
        System.out.println(response.body());
    }
}
```

</Tab>

<Tab name="Python"> ```py import requests

headers = {
    "Authorization": "Bearer {token}"
}

response = requests.get("https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}",
    headers=headers
)
print(response.json())
```

</Tab>

<Tab name="C#"> ```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/designs/{designId}/comments/{threadId}"),
  Headers =
  {
    { "Authorization", "Bearer {token}" },
  },
};

using (var response = await client.SendAsync(request))
{
  response.EnsureSuccessStatusCode();
  var body = await response.Content.ReadAsStringAsync();
  Console.WriteLine(body);
};
```

</Tab>

<Tab name="Go"> ```go package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	url := "https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}"
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Add("Authorization", "Bearer {token}")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
```

</Tab>

<Tab name="PHP"> ```php $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}", CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => array( 'Authorization: Bearer {token}', ), ));

$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);

if (empty($err)) {
  echo $response;
} else {
  echo "Error: " . $err;
}
```

</Tab>

<Tab name="Ruby"> ```ruby require 'net/http' require 'uri'

url = URI('https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}')
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request['Authorization'] = 'Bearer {token}'

response = http.request(request)
puts response.read_body
```

</Tab> </Tabs>

Success response

If successful, the endpoint returns a 200 response with a JSON body with the following parameters:

<Prop.List> <Prop name="thread" type="Thread" mode="output"> A discussion thread on a design.

The `type` of the thread can be found in the `thread_type` object, along with additional type-specific properties.
The `author` of the thread might be missing if that user account no longer exists.

&lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;thread&lt;/strong&gt;&lt;/&gt;} defaultExpanded={true}&gt;
  &lt;Prop.List&gt;
    &lt;Prop name="id" type="string" required mode="output"&gt;
      The ID of the thread.

      You can use this ID to create replies to the thread using the Create reply API.
    &lt;/Prop&gt;

    &lt;Prop name="design_id" type="string" required mode="output"&gt;
      The ID of the design that the discussion thread is on.
    &lt;/Prop&gt;

    &lt;Prop name="thread_type" type="ThreadType" required mode="output"&gt;
      The type of the discussion thread, along with additional type-specific properties.

      &lt;Tabs&gt;
        &lt;Tab name="comment"&gt;
          A comment thread.

          &lt;Prop.List&gt;
            &lt;Prop name="type" type="string" required mode="output"&gt;
              &lt;Prop.Extras&gt;
                **Available values:** The only valid value is `comment`.
              &lt;/Prop.Extras&gt;
            &lt;/Prop&gt;

            &lt;Prop name="content" type="CommentContent" required mode="output"&gt;
              The content of a comment thread or reply.

              &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;content&lt;/strong&gt;&lt;/&gt;}&gt;
                &lt;Prop.List&gt;
                  &lt;Prop name="plaintext" type="string" required mode="output"&gt;
                    The content in plaintext.
                    Any user mention tags are shown in the format `[user_id:team_id]`.
                  &lt;/Prop&gt;

                  &lt;Prop name="markdown" type="string" mode="output"&gt;
                    The content in markdown.
                    Any user mention tags are shown in the format `[user_id:team_id]`
                  &lt;/Prop&gt;
                &lt;/Prop.List&gt;
              &lt;/PillAccordion&gt;
            &lt;/Prop&gt;

            &lt;Prop name="mentions" type="object" required mode="output"&gt;
              The Canva users mentioned in the comment thread or reply.

              &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;mentions&lt;/strong&gt;&lt;/&gt;}&gt;
                &lt;Prop.List&gt;
                  &lt;Prop name="&lt;KEY&gt;" type="object of UserMentions" mode="output" required required&gt;
                    Information about the user mentioned in a comment thread or reply. Each user mention is keyed using the user's user ID and team ID separated by a colon (`user_id:team_id`).

                    ```json
                    {
                      "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP": {
                        "tag": "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP",
                        "user": {
                          "user_id": "oUnPjZ2k2yuhftbWF7873o",
                          "team_id": "oBpVhLW22VrqtwKgaayRbP",
                          "display_name": "John Doe"
                        }
                      }
                    }
                    ```

                    &lt;Prop.List&gt;
                      &lt;Prop name="tag" type="string" required mode="output"&gt;
                        The mention tag for the user mentioned in the comment thread or reply content. This has the format of the user's user ID and team ID separated by a colon (`user_id:team_id`).
                      &lt;/Prop&gt;

                      &lt;Prop name="user" type="TeamUser" required mode="output"&gt;
                        Metadata for the user, consisting of the User ID, Team ID, and display name.

                        &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;user&lt;/strong&gt;&lt;/&gt;}&gt;
                          &lt;Prop.List&gt;
                            &lt;Prop name="user_id" type="string" mode="output"&gt;
                              The ID of the user.
                            &lt;/Prop&gt;

                            &lt;Prop name="team_id" type="string" mode="output"&gt;
                              The ID of the user's Canva Team.
                            &lt;/Prop&gt;

                            &lt;Prop name="display_name" type="string" mode="output"&gt;
                              The name of the user as shown in the Canva UI.
                            &lt;/Prop&gt;
                          &lt;/Prop.List&gt;
                        &lt;/PillAccordion&gt;
                      &lt;/Prop&gt;
                    &lt;/Prop.List&gt;
                  &lt;/Prop&gt;
                &lt;/Prop.List&gt;
              &lt;/PillAccordion&gt;
            &lt;/Prop&gt;

            &lt;Prop name="assignee" type="User" mode="output"&gt;
              Metadata for the user, consisting of the User ID and display name.

              &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;assignee&lt;/strong&gt;&lt;/&gt;}&gt;
                &lt;Prop.List&gt;
                  &lt;Prop name="id" type="string" required mode="output"&gt;
                    The ID of the user.
                  &lt;/Prop&gt;

                  &lt;Prop name="display_name" type="string" mode="output"&gt;
                    The name of the user as shown in the Canva UI.
                  &lt;/Prop&gt;
                &lt;/Prop.List&gt;
              &lt;/PillAccordion&gt;
            &lt;/Prop&gt;

            &lt;Prop name="resolver" type="User" mode="output"&gt;
              Metadata for the user, consisting of the User ID and display name.

              &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;resolver&lt;/strong&gt;&lt;/&gt;}&gt;
                &lt;Prop.List&gt;
                  &lt;Prop name="id" type="string" required mode="output"&gt;
                    The ID of the user.
                  &lt;/Prop&gt;

                  &lt;Prop name="display_name" type="string" mode="output"&gt;
                    The name of the user as shown in the Canva UI.
                  &lt;/Prop&gt;
                &lt;/Prop.List&gt;
              &lt;/PillAccordion&gt;
            &lt;/Prop&gt;
          &lt;/Prop.List&gt;
        &lt;/Tab&gt;

        &lt;Tab name="suggestion"&gt;
          A suggestion thread.

          &lt;Prop.List&gt;
            &lt;Prop name="type" type="string" required mode="output"&gt;
              &lt;Prop.Extras&gt;
                **Available values:** The only valid value is `suggestion`.
              &lt;/Prop.Extras&gt;
            &lt;/Prop&gt;

            &lt;Prop name="suggested_edits" type="SuggestedEdit[]" required mode="output"&gt;
              The type of the suggested edit, along with additional type-specific properties.

              &lt;Prop.Extras&gt;
                **Minimum items:** `1`
              &lt;/Prop.Extras&gt;

              &lt;Tabs&gt;
                &lt;Tab name="add"&gt;
                  A suggestion to add some text.

                  &lt;Prop.List&gt;
                    &lt;Prop name="type" type="string" required mode="output"&gt;
                      &lt;Prop.Extras&gt;
                        **Available values:** The only valid value is `add`.
                      &lt;/Prop.Extras&gt;
                    &lt;/Prop&gt;
                  &lt;/Prop.List&gt;
                &lt;/Tab&gt;

                &lt;Tab name="delete"&gt;
                  A suggestion to delete some text.

                  &lt;Prop.List&gt;
                    &lt;Prop name="type" type="string" required mode="output"&gt;
                      &lt;Prop.Extras&gt;
                        **Available values:** The only valid value is `delete`.
                      &lt;/Prop.Extras&gt;
                    &lt;/Prop&gt;
                  &lt;/Prop.List&gt;
                &lt;/Tab&gt;

                &lt;Tab name="format"&gt;
                  A suggestion to format some text.

                  &lt;Prop.List&gt;
                    &lt;Prop name="type" type="string" required mode="output"&gt;
                      &lt;Prop.Extras&gt;
                        **Available values:** The only valid value is `format`.
                      &lt;/Prop.Extras&gt;
                    &lt;/Prop&gt;

                    &lt;Prop name="format" type="string" required mode="output"&gt;
                      The suggested format change.

                      &lt;Prop.Extras&gt;
                        **Available values:**

                        * `font_family`
                        * `font_size`
                        * `font_weight`
                        * `font_style`
                        * `color`
                        * `background_color`
                        * `decoration`
                        * `strikethrough`
                        * `link`
                        * `letter_spacing`
                        * `line_height`
                        * `direction`
                        * `text_align`
                        * `list_marker`
                        * `list_level`
                        * `margin_inline_start`
                        * `text_indent`
                        * `font_size_modifier`
                        * `vertical_align`
                      &lt;/Prop.Extras&gt;
                    &lt;/Prop&gt;
                  &lt;/Prop.List&gt;
                &lt;/Tab&gt;
              &lt;/Tabs&gt;
            &lt;/Prop&gt;

            &lt;Prop name="status" type="string" required mode="output"&gt;
              The current status of the suggestion.

              &lt;Prop.Extras&gt;
                **Available values:**

                * `open`: A suggestion was made, but it hasn't been accepted or rejected yet.
                * `accepted`: A suggestion was accepted and applied to the design.
                * `rejected`: A suggestion was rejected and not applied to the design.
              &lt;/Prop.Extras&gt;
            &lt;/Prop&gt;
          &lt;/Prop.List&gt;
        &lt;/Tab&gt;
      &lt;/Tabs&gt;
    &lt;/Prop&gt;

    &lt;Prop name="created_at" type="integer" required mode="output"&gt;
      When the thread was created, as a Unix timestamp
      (in seconds since the Unix Epoch).
    &lt;/Prop&gt;

    &lt;Prop name="updated_at" type="integer" required mode="output"&gt;
      When the thread was last updated, as a Unix timestamp
      (in seconds since the Unix Epoch).
    &lt;/Prop&gt;

    &lt;Prop name="author" type="User" mode="output"&gt;
      Metadata for the user, consisting of the User ID and display name.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;author&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="id" type="string" required mode="output"&gt;
            The ID of the user.
          &lt;/Prop&gt;

          &lt;Prop name="display_name" type="string" mode="output"&gt;
            The name of the user as shown in the Canva UI.
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;
  &lt;/Prop.List&gt;
&lt;/PillAccordion&gt;

</Prop>

<Prop name="comment" type="Comment" deprecated mode="output"> The comment object, which contains metadata about the comment. Deprecated in favor of the new thread object.

&lt;Tabs&gt;
  &lt;Tab name="parent"&gt;
    The type of comment. When creating a new parent (top-level)
    comment, the `type` is `parent`.

    &lt;Prop.List&gt;
      &lt;Prop name="type" type="string" required mode="output"&gt;
        The type of comment. When creating a new parent (top-level)
        comment, the `type` is `parent`.

        &lt;Prop.Extras&gt;
          **Available values:** The only valid value is `parent`.
        &lt;/Prop.Extras&gt;
      &lt;/Prop&gt;

      &lt;Prop name="id" type="string" required mode="output"&gt;
        The ID of the comment.

        You can use this ID to create replies to the comment using the Create reply API.
      &lt;/Prop&gt;

      &lt;Prop name="message" type="string" required mode="output"&gt;
        The comment message. This is the comment body shown in the Canva UI.
        User mentions are shown here in the format `[user_id:team_id]`.
      &lt;/Prop&gt;

      &lt;Prop name="author" type="User" required mode="output"&gt;
        Metadata for the user, consisting of the User ID and display name.

        &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;author&lt;/strong&gt;&lt;/&gt;}&gt;
          &lt;Prop.List&gt;
            &lt;Prop name="id" type="string" required mode="output"&gt;
              The ID of the user.
            &lt;/Prop&gt;

            &lt;Prop name="display_name" type="string" deprecated mode="output"&gt;
              The name of the user as shown in the Canva UI.
            &lt;/Prop&gt;
          &lt;/Prop.List&gt;
        &lt;/PillAccordion&gt;
      &lt;/Prop&gt;

      &lt;Prop name="created_at" type="integer" deprecated mode="output"&gt;
        When the comment or reply was created, as a Unix timestamp
        (in seconds since the Unix Epoch).
      &lt;/Prop&gt;

      &lt;Prop name="updated_at" type="integer" deprecated mode="output"&gt;
        When the comment or reply was last updated, as a Unix timestamp
        (in seconds since the Unix Epoch).
      &lt;/Prop&gt;

      &lt;Prop name="assignee" type="User" deprecated mode="output"&gt;
        Metadata for the user, consisting of the User ID and display name.

        &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;assignee&lt;/strong&gt;&lt;/&gt;}&gt;
          &lt;Prop.List&gt;
            &lt;Prop name="id" type="string" required mode="output"&gt;
              The ID of the user.
            &lt;/Prop&gt;

            &lt;Prop name="display_name" type="string" deprecated mode="output"&gt;
              The name of the user as shown in the Canva UI.
            &lt;/Prop&gt;
          &lt;/Prop.List&gt;
        &lt;/PillAccordion&gt;
      &lt;/Prop&gt;

      &lt;Prop name="resolver" type="User" deprecated mode="output"&gt;
        Metadata for the user, consisting of the User ID and display name.

        &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;resolver&lt;/strong&gt;&lt;/&gt;}&gt;
          &lt;Prop.List&gt;
            &lt;Prop name="id" type="string" required mode="output"&gt;
              The ID of the user.
            &lt;/Prop&gt;

            &lt;Prop name="display_name" type="string" deprecated mode="output"&gt;
              The name of the user as shown in the Canva UI.
            &lt;/Prop&gt;
          &lt;/Prop.List&gt;
        &lt;/PillAccordion&gt;
      &lt;/Prop&gt;

      &lt;Prop name="mentions" type="object" required mode="output"&gt;
        The Canva users mentioned in the comment.

        &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;mentions&lt;/strong&gt;&lt;/&gt;}&gt;
          &lt;Prop.List&gt;
            &lt;Prop name="&lt;KEY&gt;" type="object of TeamUsers" mode="output" required&gt;
              Metadata for the user, consisting of the User ID, Team ID, and display name.

              &lt;Prop.List&gt;
                &lt;Prop name="user_id" type="string" deprecated mode="output"&gt;
                  The ID of the user.
                &lt;/Prop&gt;

                &lt;Prop name="team_id" type="string" deprecated mode="output"&gt;
                  The ID of the user's Canva Team.
                &lt;/Prop&gt;

                &lt;Prop name="display_name" type="string" deprecated mode="output"&gt;
                  The name of the user as shown in the Canva UI.
                &lt;/Prop&gt;
              &lt;/Prop.List&gt;
            &lt;/Prop&gt;
          &lt;/Prop.List&gt;
        &lt;/PillAccordion&gt;
      &lt;/Prop&gt;

      &lt;Prop name="attached_to" type="CommentObject" deprecated mode="output"&gt;
        Identifying information about the object (such as a design) that the comment is attached to.

        &lt;Tabs&gt;
          &lt;Tab name="design"&gt;
            If the comment is attached to a Canva Design.

            &lt;Prop.List&gt;
              &lt;Prop name="type" type="string" required mode="output"&gt;
                &lt;Prop.Extras&gt;
                  **Available values:** The only valid value is `design`.
                &lt;/Prop.Extras&gt;
              &lt;/Prop&gt;

              &lt;Prop name="design_id" type="string" required mode="output"&gt;
                The ID of the design this comment is attached to.
              &lt;/Prop&gt;
            &lt;/Prop.List&gt;
          &lt;/Tab&gt;
        &lt;/Tabs&gt;
      &lt;/Prop&gt;
    &lt;/Prop.List&gt;
  &lt;/Tab&gt;

  &lt;Tab name="reply"&gt;
    The type of comment. When creating a reply to a top-level
    comment, the `type` is `reply`.

    &lt;Prop.List&gt;
      &lt;Prop name="type" type="string" required mode="output"&gt;
        The type of comment. When creating a reply to a top-level
        comment, the `type` is `reply`.

        &lt;Prop.Extras&gt;
          **Available values:** The only valid value is `reply`.
        &lt;/Prop.Extras&gt;
      &lt;/Prop&gt;

      &lt;Prop name="id" type="string" required mode="output"&gt;
        The ID of the comment.
      &lt;/Prop&gt;

      &lt;Prop name="message" type="string" required mode="output"&gt;
        The comment message. This is the comment body shown in the Canva UI.
        User mentions are shown here in the format `[user_id:team_id]`.
      &lt;/Prop&gt;

      &lt;Prop name="author" type="User" required mode="output"&gt;
        Metadata for the user, consisting of the User ID and display name.

        &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;author&lt;/strong&gt;&lt;/&gt;}&gt;
          &lt;Prop.List&gt;
            &lt;Prop name="id" type="string" required mode="output"&gt;
              The ID of the user.
            &lt;/Prop&gt;

            &lt;Prop name="display_name" type="string" deprecated mode="output"&gt;
              The name of the user as shown in the Canva UI.
            &lt;/Prop&gt;
          &lt;/Prop.List&gt;
        &lt;/PillAccordion&gt;
      &lt;/Prop&gt;

      &lt;Prop name="thread_id" type="string" required mode="output"&gt;
        The ID of the comment thread this reply is in. This ID is the same as the `id` of the
        parent comment.
      &lt;/Prop&gt;

      &lt;Prop name="created_at" type="integer" deprecated mode="output"&gt;
        When the comment or reply was created, as a Unix timestamp
        (in seconds since the Unix Epoch).
      &lt;/Prop&gt;

      &lt;Prop name="updated_at" type="integer" deprecated mode="output"&gt;
        When the comment or reply was last updated, as a Unix timestamp
        (in seconds since the Unix Epoch).
      &lt;/Prop&gt;

      &lt;Prop name="mentions" type="object" required mode="output"&gt;
        The Canva users mentioned in the comment.

        &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;mentions&lt;/strong&gt;&lt;/&gt;}&gt;
          &lt;Prop.List&gt;
            &lt;Prop name="&lt;KEY&gt;" type="object of TeamUsers" mode="output" required&gt;
              Metadata for the user, consisting of the User ID, Team ID, and display name.

              &lt;Prop.List&gt;
                &lt;Prop name="user_id" type="string" deprecated mode="output"&gt;
                  The ID of the user.
                &lt;/Prop&gt;

                &lt;Prop name="team_id" type="string" deprecated mode="output"&gt;
                  The ID of the user's Canva Team.
                &lt;/Prop&gt;

                &lt;Prop name="display_name" type="string" deprecated mode="output"&gt;
                  The name of the user as shown in the Canva UI.
                &lt;/Prop&gt;
              &lt;/Prop.List&gt;
            &lt;/Prop&gt;
          &lt;/Prop.List&gt;
        &lt;/PillAccordion&gt;
      &lt;/Prop&gt;

      &lt;Prop name="attached_to" type="CommentObject" deprecated mode="output"&gt;
        Identifying information about the object (such as a design) that the comment is attached to.

        &lt;Tabs&gt;
          &lt;Tab name="design"&gt;
            If the comment is attached to a Canva Design.

            &lt;Prop.List&gt;
              &lt;Prop name="type" type="string" required mode="output"&gt;
                &lt;Prop.Extras&gt;
                  **Available values:** The only valid value is `design`.
                &lt;/Prop.Extras&gt;
              &lt;/Prop&gt;

              &lt;Prop name="design_id" type="string" required mode="output"&gt;
                The ID of the design this comment is attached to.
              &lt;/Prop&gt;
            &lt;/Prop.List&gt;
          &lt;/Tab&gt;
        &lt;/Tabs&gt;
      &lt;/Prop&gt;
    &lt;/Prop.List&gt;
  &lt;/Tab&gt;
&lt;/Tabs&gt;

</Prop> </Prop.List>

Example response

json
{
  "thread": {
    "id": "KeAbiEAjZEj",
    "design_id": "DAFVztcvd9z",
    "thread_type": {
      "type": "comment",
      "content": {
        "plaintext": "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!",
        "markdown": "*_Great work_* [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!"
      },
      "mentions": {
        "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP": {
          "tag": "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP",
          "user": {
            "user_id": "oUnPjZ2k2yuhftbWF7873o",
            "team_id": "oBpVhLW22VrqtwKgaayRbP",
            "display_name": "John Doe"
          }
        }
      },
      "assignee": {
        "id": "uKakKUfI03Fg8k2gZ6OkT",
        "display_name": "John Doe"
      },
      "resolver": {
        "id": "uKakKUfI03Fg8k2gZ6OkT",
        "display_name": "John Doe"
      }
    },
    "author": {
      "id": "uKakKUfI03Fg8k2gZ6OkT",
      "display_name": "John Doe"
    },
    "created_at": 1692928800,
    "updated_at": 1692928900
  }
}

Error responses

403 Forbidden

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "permission_denied",
  "message": "Not allowed to fetch this comment"
}

404 Not Found

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "thread_not_found",
  "message": "No thread with ID {threadId} found"
}

Get Reply

Get a comment reply.

<Warning> 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.
  • Public integrations that use preview APIs will not pass the review process, and can't be made available to all Canva users. </Warning>

Gets a reply to a comment or suggestion thread on a design. For information on comments and how they're used in the Canva UI, see the Canva Help Center.

HTTP method and URL path

GET https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies/{replyId}

This operation is rate limited to 100 requests per minute for each user of your integration.

Authentication and authorization

This endpoint requires a valid access token that acts on behalf of a user.

Scopes

The access token must have all the following scopes (permissions):

  • comment:read

Header parameters

<Prop.List> <Prop name="Authorization" type="string" required> Provides credentials to authenticate the request, in the form of a Bearer token.

For example: `Authorization: Bearer {token}`

</Prop> </Prop.List>

Path parameters

<Prop.List> <Prop name="designId" type="string" required> The design ID. </Prop>

<Prop name="threadId" type="string" required> The ID of the thread. </Prop>

<Prop name="replyId" type="string" required> The ID of the reply. </Prop> </Prop.List>

Example request

Examples for using the /v1/designs/{designId}/comments/{threadId}/replies/{replyId} endpoint:

<Tabs storageKey="example.language" disableContentTransition> <Tab name="cURL"> sh curl --request GET 'https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies/{replyId}' \ --header 'Authorization: Bearer {token}' </Tab>

<Tab name="Node.js"> ```js const fetch = require("node-fetch");

fetch("https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies/{replyId}", {
  method: "GET",
  headers: {
    "Authorization": "Bearer {token}",
  },
})
  .then(async (response) => {
    const data = await response.json();
    console.log(data);
  })
  .catch(err => console.error(err));
```

</Tab>

<Tab name="Java"> ```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/designs/{designId}/comments/{threadId}/replies/{replyId}"))
            .header("Authorization", "Bearer {token}")
            .method("GET", HttpRequest.BodyPublishers.noBody())
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient().send(
            request,
            HttpResponse.BodyHandlers.ofString()
        );
        System.out.println(response.body());
    }
}
```

</Tab>

<Tab name="Python"> ```py import requests

headers = {
    "Authorization": "Bearer {token}"
}

response = requests.get("https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies/{replyId}",
    headers=headers
)
print(response.json())
```

</Tab>

<Tab name="C#"> ```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/designs/{designId}/comments/{threadId}/replies/{replyId}"),
  Headers =
  {
    { "Authorization", "Bearer {token}" },
  },
};

using (var response = await client.SendAsync(request))
{
  response.EnsureSuccessStatusCode();
  var body = await response.Content.ReadAsStringAsync();
  Console.WriteLine(body);
};
```

</Tab>

<Tab name="Go"> ```go package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	url := "https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies/{replyId}"
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Add("Authorization", "Bearer {token}")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
```

</Tab>

<Tab name="PHP"> ```php $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies/{replyId}", CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => array( 'Authorization: Bearer {token}', ), ));

$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);

if (empty($err)) {
  echo $response;
} else {
  echo "Error: " . $err;
}
```

</Tab>

<Tab name="Ruby"> ```ruby require 'net/http' require 'uri'

url = URI('https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies/{replyId}')
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request['Authorization'] = 'Bearer {token}'

response = http.request(request)
puts response.read_body
```

</Tab> </Tabs>

Success response

If successful, the endpoint returns a 200 response with a JSON body with the following parameters:

<Prop.List> <Prop name="reply" type="Reply" required mode="output"> A reply to a thread.

The `author` of the reply might be missing if that user account no longer exists.

&lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;reply&lt;/strong&gt;&lt;/&gt;} defaultExpanded={true}&gt;
  &lt;Prop.List&gt;
    &lt;Prop name="id" type="string" required mode="output"&gt;
      The ID of the reply.
    &lt;/Prop&gt;

    &lt;Prop name="design_id" type="string" required mode="output"&gt;
      The ID of the design that the thread for this reply is attached to.
    &lt;/Prop&gt;

    &lt;Prop name="thread_id" type="string" required mode="output"&gt;
      The ID of the thread this reply is in.
    &lt;/Prop&gt;

    &lt;Prop name="content" type="CommentContent" required mode="output"&gt;
      The content of a comment thread or reply.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;content&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="plaintext" type="string" required mode="output"&gt;
            The content in plaintext.
            Any user mention tags are shown in the format `[user_id:team_id]`.
          &lt;/Prop&gt;

          &lt;Prop name="markdown" type="string" mode="output"&gt;
            The content in markdown.
            Any user mention tags are shown in the format `[user_id:team_id]`
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;

    &lt;Prop name="mentions" type="object" required mode="output"&gt;
      The Canva users mentioned in the comment thread or reply.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;mentions&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="&lt;KEY&gt;" type="object of UserMentions" mode="output" required required&gt;
            Information about the user mentioned in a comment thread or reply. Each user mention is keyed using the user's user ID and team ID separated by a colon (`user_id:team_id`).

            ```json
            {
              "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP": {
                "tag": "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP",
                "user": {
                  "user_id": "oUnPjZ2k2yuhftbWF7873o",
                  "team_id": "oBpVhLW22VrqtwKgaayRbP",
                  "display_name": "John Doe"
                }
              }
            }
            ```

            &lt;Prop.List&gt;
              &lt;Prop name="tag" type="string" required mode="output"&gt;
                The mention tag for the user mentioned in the comment thread or reply content. This has the format of the user's user ID and team ID separated by a colon (`user_id:team_id`).
              &lt;/Prop&gt;

              &lt;Prop name="user" type="TeamUser" required mode="output"&gt;
                Metadata for the user, consisting of the User ID, Team ID, and display name.

                &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;user&lt;/strong&gt;&lt;/&gt;}&gt;
                  &lt;Prop.List&gt;
                    &lt;Prop name="user_id" type="string" mode="output"&gt;
                      The ID of the user.
                    &lt;/Prop&gt;

                    &lt;Prop name="team_id" type="string" mode="output"&gt;
                      The ID of the user's Canva Team.
                    &lt;/Prop&gt;

                    &lt;Prop name="display_name" type="string" mode="output"&gt;
                      The name of the user as shown in the Canva UI.
                    &lt;/Prop&gt;
                  &lt;/Prop.List&gt;
                &lt;/PillAccordion&gt;
              &lt;/Prop&gt;
            &lt;/Prop.List&gt;
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;

    &lt;Prop name="created_at" type="integer" required mode="output"&gt;
      When the reply was created, as a Unix timestamp
      (in seconds since the Unix Epoch).
    &lt;/Prop&gt;

    &lt;Prop name="updated_at" type="integer" required mode="output"&gt;
      When the reply was last updated, as a Unix timestamp
      (in seconds since the Unix Epoch).
    &lt;/Prop&gt;

    &lt;Prop name="author" type="User" mode="output"&gt;
      Metadata for the user, consisting of the User ID and display name.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;author&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="id" type="string" required mode="output"&gt;
            The ID of the user.
          &lt;/Prop&gt;

          &lt;Prop name="display_name" type="string" mode="output"&gt;
            The name of the user as shown in the Canva UI.
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;
  &lt;/Prop.List&gt;
&lt;/PillAccordion&gt;

</Prop> </Prop.List>

Example response

json
{
  "reply": {
    "id": "KeAZEAjijEb",
    "design_id": "DAFVztcvd9z",
    "thread_id": "KeAbiEAjZEj",
    "author": {
      "id": "uKakKUfI03Fg8k2gZ6OkT",
      "display_name": "John Doe"
    },
    "content": {
      "plaintext": "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!",
      "markdown": "*_Great work_* [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!"
    },
    "mentions": {
      "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP": {
        "tag": "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP",
        "user": {
          "user_id": "oUnPjZ2k2yuhftbWF7873o",
          "team_id": "oBpVhLW22VrqtwKgaayRbP",
          "display_name": "John Doe"
        }
      }
    },
    "created_at": 1692929800,
    "updated_at": 1692929900
  }
}

Error responses

403 Forbidden

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "permission_denied",
  "message": "Not allowed to fetch this reply"
}

404 Not Found

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "reply_not_found",
  "message": "Reply with ID {replyId} not found"
}

List Replies

List the replies to a comment on a design.

<Warning> 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.
  • Public integrations that use preview APIs will not pass the review process, and can't be made available to all Canva users. </Warning>

Retrieves a list of replies for a comment or suggestion thread on a design.

For information on comments and how they're used in the Canva UI, see the Canva Help Center.

HTTP method and URL path

GET https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies

This operation is rate limited to 100 requests per minute for each user of your integration.

Authentication and authorization

This endpoint requires a valid access token that acts on behalf of a user.

Scopes

The access token must have all the following scopes (permissions):

  • comment:read

Header parameters

<Prop.List> <Prop name="Authorization" type="string" required> Provides credentials to authenticate the request, in the form of a Bearer token.

For example: `Authorization: Bearer {token}`

</Prop> </Prop.List>

Path parameters

<Prop.List> <Prop name="designId" type="string" required> The design ID. </Prop>

<Prop name="threadId" type="string" required> The ID of the thread. </Prop> </Prop.List>

Query parameters

<Prop.List> <Prop name="limit" type="integer"> The number of replies to return.

&lt;Prop.Extras&gt;
  **Minimum:** `1`

  **Maximum:** `100`

  **Default value:** `50`
&lt;/Prop.Extras&gt;

</Prop>

<Prop name="continuation" type="string"> If the success response contains a continuation token, the list contains more items you can list. You can use this token as a query parameter and retrieve more items from the list, for example ?continuation={continuation}.

To retrieve all items, you might need to make multiple requests.

</Prop> </Prop.List>

Example request

Examples for using the /v1/designs/{designId}/comments/{threadId}/replies endpoint:

<Tabs storageKey="example.language" disableContentTransition> <Tab name="cURL"> sh curl --request GET 'https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies' \ --header 'Authorization: Bearer {token}' </Tab>

<Tab name="Node.js"> ```js const fetch = require("node-fetch");

fetch("https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies", {
  method: "GET",
  headers: {
    "Authorization": "Bearer {token}",
  },
})
  .then(async (response) => {
    const data = await response.json();
    console.log(data);
  })
  .catch(err => console.error(err));
```

</Tab>

<Tab name="Java"> ```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/designs/{designId}/comments/{threadId}/replies"))
            .header("Authorization", "Bearer {token}")
            .method("GET", HttpRequest.BodyPublishers.noBody())
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient().send(
            request,
            HttpResponse.BodyHandlers.ofString()
        );
        System.out.println(response.body());
    }
}
```

</Tab>

<Tab name="Python"> ```py import requests

headers = {
    "Authorization": "Bearer {token}"
}

response = requests.get("https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies",
    headers=headers
)
print(response.json())
```

</Tab>

<Tab name="C#"> ```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/designs/{designId}/comments/{threadId}/replies"),
  Headers =
  {
    { "Authorization", "Bearer {token}" },
  },
};

using (var response = await client.SendAsync(request))
{
  response.EnsureSuccessStatusCode();
  var body = await response.Content.ReadAsStringAsync();
  Console.WriteLine(body);
};
```

</Tab>

<Tab name="Go"> ```go package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	url := "https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies"
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Add("Authorization", "Bearer {token}")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
```

</Tab>

<Tab name="PHP"> ```php $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies", CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => array( 'Authorization: Bearer {token}', ), ));

$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);

if (empty($err)) {
  echo $response;
} else {
  echo "Error: " . $err;
}
```

</Tab>

<Tab name="Ruby"> ```ruby require 'net/http' require 'uri'

url = URI('https://api.canva.com/rest/v1/designs/{designId}/comments/{threadId}/replies')
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request['Authorization'] = 'Bearer {token}'

response = http.request(request)
puts response.read_body
```

</Tab> </Tabs>

Success response

If successful, the endpoint returns a 200 response with a JSON body with the following parameters:

<Prop.List> <Prop name="items" type="Reply[]" required mode="output"> A reply to a thread.

The `author` of the reply might be missing if that user account no longer exists.

&lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;items&lt;/strong&gt;&lt;/&gt;} defaultExpanded={true}&gt;
  &lt;Prop.List&gt;
    &lt;Prop name="id" type="string" required mode="output"&gt;
      The ID of the reply.
    &lt;/Prop&gt;

    &lt;Prop name="design_id" type="string" required mode="output"&gt;
      The ID of the design that the thread for this reply is attached to.
    &lt;/Prop&gt;

    &lt;Prop name="thread_id" type="string" required mode="output"&gt;
      The ID of the thread this reply is in.
    &lt;/Prop&gt;

    &lt;Prop name="content" type="CommentContent" required mode="output"&gt;
      The content of a comment thread or reply.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;content&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="plaintext" type="string" required mode="output"&gt;
            The content in plaintext.
            Any user mention tags are shown in the format `[user_id:team_id]`.
          &lt;/Prop&gt;

          &lt;Prop name="markdown" type="string" mode="output"&gt;
            The content in markdown.
            Any user mention tags are shown in the format `[user_id:team_id]`
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;

    &lt;Prop name="mentions" type="object" required mode="output"&gt;
      The Canva users mentioned in the comment thread or reply.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;mentions&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="&lt;KEY&gt;" type="object of UserMentions" mode="output" required required&gt;
            Information about the user mentioned in a comment thread or reply. Each user mention is keyed using the user's user ID and team ID separated by a colon (`user_id:team_id`).

            ```json
            {
              "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP": {
                "tag": "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP",
                "user": {
                  "user_id": "oUnPjZ2k2yuhftbWF7873o",
                  "team_id": "oBpVhLW22VrqtwKgaayRbP",
                  "display_name": "John Doe"
                }
              }
            }
            ```

            &lt;Prop.List&gt;
              &lt;Prop name="tag" type="string" required mode="output"&gt;
                The mention tag for the user mentioned in the comment thread or reply content. This has the format of the user's user ID and team ID separated by a colon (`user_id:team_id`).
              &lt;/Prop&gt;

              &lt;Prop name="user" type="TeamUser" required mode="output"&gt;
                Metadata for the user, consisting of the User ID, Team ID, and display name.

                &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;user&lt;/strong&gt;&lt;/&gt;}&gt;
                  &lt;Prop.List&gt;
                    &lt;Prop name="user_id" type="string" mode="output"&gt;
                      The ID of the user.
                    &lt;/Prop&gt;

                    &lt;Prop name="team_id" type="string" mode="output"&gt;
                      The ID of the user's Canva Team.
                    &lt;/Prop&gt;

                    &lt;Prop name="display_name" type="string" mode="output"&gt;
                      The name of the user as shown in the Canva UI.
                    &lt;/Prop&gt;
                  &lt;/Prop.List&gt;
                &lt;/PillAccordion&gt;
              &lt;/Prop&gt;
            &lt;/Prop.List&gt;
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;

    &lt;Prop name="created_at" type="integer" required mode="output"&gt;
      When the reply was created, as a Unix timestamp
      (in seconds since the Unix Epoch).
    &lt;/Prop&gt;

    &lt;Prop name="updated_at" type="integer" required mode="output"&gt;
      When the reply was last updated, as a Unix timestamp
      (in seconds since the Unix Epoch).
    &lt;/Prop&gt;

    &lt;Prop name="author" type="User" mode="output"&gt;
      Metadata for the user, consisting of the User ID and display name.

      &lt;PillAccordion title={&lt;&gt;Properties of &lt;strong&gt;author&lt;/strong&gt;&lt;/&gt;}&gt;
        &lt;Prop.List&gt;
          &lt;Prop name="id" type="string" required mode="output"&gt;
            The ID of the user.
          &lt;/Prop&gt;

          &lt;Prop name="display_name" type="string" mode="output"&gt;
            The name of the user as shown in the Canva UI.
          &lt;/Prop&gt;
        &lt;/Prop.List&gt;
      &lt;/PillAccordion&gt;
    &lt;/Prop&gt;
  &lt;/Prop.List&gt;
&lt;/PillAccordion&gt;

</Prop>

<Prop name="continuation" type="string" mode="output"> If the success response contains a continuation token, the list contains more items you can list. You can use this token as a query parameter and retrieve more items from the list, for example ?continuation={continuation}.

To retrieve all items, you might need to make multiple requests.

</Prop> </Prop.List>

Example response

json
{
  "continuation": "RkFGMgXlsVTDbMd:MR3L0QjiaUzycIAjx0yMyuNiV0OildoiOwL0x32G4NjNu4FwtAQNxowUQNMMYN",
  "items": [
    {
      "id": "KeAZEAjijEb",
      "design_id": "DAFVztcvd9z",
      "thread_id": "KeAbiEAjZEj",
      "author": {
        "id": "uKakKUfI03Fg8k2gZ6OkT",
        "display_name": "John Doe"
      },
      "content": {
        "plaintext": "Great work [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!",
        "markdown": "*_Great work_* [oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP]!"
      },
      "mentions": {
        "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP": {
          "tag": "oUnPjZ2k2yuhftbWF7873o:oBpVhLW22VrqtwKgaayRbP",
          "user": {
            "user_id": "oUnPjZ2k2yuhftbWF7873o",
            "team_id": "oBpVhLW22VrqtwKgaayRbP",
            "display_name": "John Doe"
          }
        }
      },
      "created_at": 1692929800,
      "updated_at": 1692929900
    }
  ]
}

Error responses

403 Forbidden

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "permission_denied",
  "message": "Not allowed to fetch replies"
}

404 Not Found

<Prop.List> <Prop name="code" type="string" required mode="output"> A short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses. </Prop>

<Prop name="message" type="string" required mode="output"> A human-readable description of what went wrong. </Prop> </Prop.List>

Example error response

json
{
  "code": "design_or_thread_not_found",
  "message": "Design or comment not found"
}

Canva Developer Documentation SOP Site