> ## Documentation Index > Fetch the complete documentation index at: https://www.canva.dev/docs/apps/llms.txt > Use this file to discover all available pages before exploring further. # Create thread Create a new comment thread on a design. This API is currently provided as a preview. Be aware of the following: * There might be unannounced breaking changes. * Any breaking changes to preview APIs won't produce a new [API version](https://www.canva.dev/docs/apps/rest-apis/versions/). * Public apps that use preview APIs will not pass the review process, and can't be made available to all Canva users. 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](https://www.canva.com/help/comments/). ## 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 app. ## Authentication and authorization This endpoint requires a valid access token that acts on behalf of a user. For more information, see [Generate an access token](/docs/apps/rest-apis/reference/authentication/generate-access-token). ### Scopes The access token must have all the following [scopes](/docs/apps/rest-apis/scopes) (permissions): * `comment:write` ## Header parameters Provides credentials to authenticate the request, in the form of a `Bearer` token. For example: `Authorization: Bearer {token}` Indicates the media type of the information sent in the request. This must be set to `application/json`. For example: `Content-Type: application/json` ## Path parameters The design ID. ## Body parameters 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. **Minimum length:** `1` **Maximum length:** `2048` Lets you assign the comment to a Canva user using their User ID. You *must* mention the assigned user in the `message`. ## Example request Examples for using the `/v1/designs/{designId}/comments` endpoint: ```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" }' ``` ```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)); ``` ```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 response = HttpClient.newHttpClient().send( request, HttpResponse.BodyHandlers.ofString() ); System.out.println(response.body()); } } ``` ```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()) ``` ```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); }; ``` ```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)) } ``` ```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; } ``` ```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 = < ## Success response If successful, the endpoint returns a `200` response with a JSON body with the following parameters: 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. Properties of thread} defaultExpanded={true}> The ID of the thread. You can use this ID to create replies to the thread using the [Create reply API](https://www.canva.dev/docs/apps/rest-apis/reference/comments/create-reply/). The ID of the design that the discussion thread is on. The type of the discussion thread, along with additional type-specific properties. A comment thread. **Available values:** The only valid value is `comment`. The content of a comment thread or reply. Properties of content}> The content in plaintext. Any user mention tags are shown in the format `[user_id:team_id]`. The content in markdown. Any user mention tags are shown in the format `[user_id:team_id]` The Canva users mentioned in the comment thread or reply. Properties of mentions}> 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" } } } ``` 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`). Metadata for the user, consisting of the User ID, Team ID, and display name. Properties of user}> The ID of the user. The ID of the user's Canva Team. The name of the user as shown in the Canva UI. Metadata for the user, consisting of the User ID and display name. Properties of assignee}> The ID of the user. The name of the user as shown in the Canva UI. Metadata for the user, consisting of the User ID and display name. Properties of resolver}> The ID of the user. The name of the user as shown in the Canva UI. A suggestion thread. **Available values:** The only valid value is `suggestion`. The type of the suggested edit, along with additional type-specific properties. **Minimum items:** `1` A suggestion to add some text. **Available values:** The only valid value is `add`. A suggestion to delete some text. **Available values:** The only valid value is `delete`. A suggestion to format some text. **Available values:** The only valid value is `format`. The suggested format change. **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` The current status of the suggestion. **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. When the thread was created, as a Unix timestamp (in seconds since the Unix Epoch). When the thread was last updated, as a Unix timestamp (in seconds since the Unix Epoch). Metadata for the user, consisting of the User ID and display name. Properties of author}> The ID of the user. The name of the user as shown in the Canva UI. ## 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 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](/docs/apps/rest-apis/error-responses/). A human-readable description of what went wrong. #### Example error responses ##### Assignee must be mentioned in comment content ```json { "code": "bad_request_body", "message": "Assignee must be mentioned in comment content" } ``` ##### Message is too long ```json { "code": "message_too_long", "message": "Message is too long" } ``` ##### Mentions with non-obfuscated IDs are not allowed for this client ```json { "code": "invalid_field", "message": "Invalid IDs" } ``` ### 403 Forbidden 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](/docs/apps/rest-apis/error-responses/). A human-readable description of what went wrong. #### Example error responses ##### Design already has the maximum number of allowed comments ```json { "code": "too_many_comments", "message": "Design already has the maximum number of allowed comments" } ``` ##### Not allowed to comment on this design ```json { "code": "permission_denied", "message": "Not allowed to comment on this design" } ``` ### 404 Not Found 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](/docs/apps/rest-apis/error-responses/). A human-readable description of what went wrong. #### Example error responses ##### Design not found ```json { "code": "design_not_found", "message": "Design not found" } ``` ##### A mentioned user could not be found ```json { "code": "user_not_found", "message": "Invalid user ID" } ``` ##### A mentioned user's team could not be found ```json { "code": "team_not_found", "message": "Invalid brand ID" } ```