Create design generation job
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.
Starts a new asynchronous job to generate a Canva design from a text brief and optional images or brand templates. A successful job includes metadata for the generated design, which is saved to the user's Canva account.
You can generate a document, presentation, or whiteboard. For presentations, you can also provide an outline of the slides to generate. Only image and brand template attachments are supported.
Requires the design_generation capability. You can check whether the user has this capability using the Get user capabilities API.
Starting a job consumes the user's AI credit allowance(opens in a new tab or window). If the user has reached their AI allowance limit, the request returns a 429 error with the credit_quota_exceeded code. Polling for the result of a job doesn't consume any of the allowance.
For more information on the workflow for using asynchronous jobs, see API requests and responses. You can check the status and get the results of jobs created with this API using the Get design generation job v2 API.
HTTP method and URL path
https://api.canva.com /rest /v1 /generationsThis operation is rate limited to 20 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.
Scopes
The access token must have all the following scopes (permissions):
design:content:write
Capabilities
The user must have at least one of the following capabilities:
design_generation
Header parameters
Content-TypestringIndicates the media type of the information sent in the request. This must be set to application/json.
For example: Content-Type: application/json
Body parameters
briefstringA description of the design to generate, including its subject, purpose, required wording, tone, and visual direction.
Minimum length: 1
Maximum length: 5000
design_typeobjectThe preset Canva design type to generate. Supports doc, presentation, and
whiteboard. The email preset and custom dimensions are not supported.
typestringAvailable values: The only valid value is preset.
namestringThe name of the design type.
Available values:
doc: A Canva doc(opens in a new tab or window); a document for Canva's online text editor.email: An email(opens in a new tab or window); for creating email campaign designs.presentation: A presentation(opens in a new tab or window); lets you create and collaborate for presenting to an audience.whiteboard: A whiteboard(opens in a new tab or window); a design which gives you infinite space to collaborate.
outlineobjectThe slide structure to follow. This property is supported only when
design_type.name is presentation.
sectionsDesignGenerationOutlineSectionV2[]One slide in a presentation outline.
Minimum items: 1
Maximum items: 100
titlestringThe slide title.
Minimum length: 1
Maximum length: 255
descriptionstringA short description of what the slide should cover.
Minimum length: 1
Maximum length: 2000
pointsstring[]Optional individual points the slide should make.
Maximum items: 50
imagesstring[]The ordered list of Canva image asset IDs to use when generating the design. You can provide at most 20 inputs across images and brand_templates combined.
Minimum items: 1
Maximum items: 20
brand_templatesstring[]The ordered list of Canva brand template IDs to use when generating the design. The user must have access to each brand template. You can provide at most 20 inputs across images and brand_templates combined.
Minimum items: 1
Maximum items: 20
Example request
Examples for using the /v1/generations endpoint:
curl --request POST 'https://api.canva.com/rest/v1/generations' \--header 'Authorization: Bearer {token}' \--header 'Content-Type: application/json' \--data '{"brief": "A 3-slide pitch deck for a solar-panel startup with an energetic, modern, blue-and-white visual direction.","design_type": {},"outline": {},"images": ["Msd59349ff"],"brand_templates": ["EDMzWSwy3BI"]}'
const fetch = require("node-fetch");fetch("https://api.canva.com/rest/v1/generations", {method: "POST",headers: {"Authorization": "Bearer {token}","Content-Type": "application/json",},body: JSON.stringify({"brief": "A 3-slide pitch deck for a solar-panel startup with an energetic, modern, blue-and-white visual direction.","design_type": {},"outline": {},"images": ["Msd59349ff"],"brand_templates": ["EDMzWSwy3BI"]}),}).then(async (response) => {const data = await response.json();console.log(data);}).catch(err => console.error(err));
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/generations")).header("Authorization", "Bearer {token}").header("Content-Type", "application/json").method("POST", HttpRequest.BodyPublishers.ofString("{\"brief\": \"A 3-slide pitch deck for a solar-panel startup with an energetic, modern, blue-and-white visual direction.\", \"design_type\": {}, \"outline\": {}, \"images\": [\"Msd59349ff\"], \"brand_templates\": [\"EDMzWSwy3BI\"]}")).build();HttpResponse<String> response = HttpClient.newHttpClient().send(request,HttpResponse.BodyHandlers.ofString());System.out.println(response.body());}}
import requestsheaders = {"Authorization": "Bearer {token}","Content-Type": "application/json"}data = {"brief": "A 3-slide pitch deck for a solar-panel startup with an energetic, modern, blue-and-white visual direction.","design_type": {},"outline": {},"images": ["Msd59349ff"],"brand_templates": ["EDMzWSwy3BI"]}response = requests.post("https://api.canva.com/rest/v1/generations",headers=headers,json=data)print(response.json())
using System.Net.Http;var client = new HttpClient();var request = new HttpRequestMessage{Method = HttpMethod.Post,RequestUri = new Uri("https://api.canva.com/rest/v1/generations"),Headers ={{ "Authorization", "Bearer {token}" },},Content = new StringContent("{\"brief\": \"A 3-slide pitch deck for a solar-panel startup with an energetic, modern, blue-and-white visual direction.\", \"design_type\": {}, \"outline\": {}, \"images\": [\"Msd59349ff\"], \"brand_templates\": [\"EDMzWSwy3BI\"]}",Encoding.UTF8,"application/json"),};using (var response = await client.SendAsync(request)){response.EnsureSuccessStatusCode();var body = await response.Content.ReadAsStringAsync();Console.WriteLine(body);};
package mainimport ("fmt""io""net/http""strings")func main() {payload := strings.NewReader(`{"brief": "A 3-slide pitch deck for a solar-panel startup with an energetic, modern, blue-and-white visual direction.","design_type": {},"outline": {},"images": ["Msd59349ff"],"brand_templates": ["EDMzWSwy3BI"]}`)url := "https://api.canva.com/rest/v1/generations"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))}
$curl = curl_init();curl_setopt_array($curl, array(CURLOPT_URL => "https://api.canva.com/rest/v1/generations",CURLOPT_CUSTOMREQUEST => "POST",CURLOPT_RETURNTRANSFER => true,CURLOPT_HTTPHEADER => array('Authorization: Bearer {token}','Content-Type: application/json',),CURLOPT_POSTFIELDS => json_encode(["brief" => "A 3-slide pitch deck for a solar-panel startup with an energetic, modern, blue-and-white visual direction.","design_type" => {},"outline" => {},"images" => ["Msd59349ff"],"brand_templates" => ["EDMzWSwy3BI"]])));$response = curl_exec($curl);$err = curl_error($curl);curl_close($curl);if (empty($err)) {echo $response;} else {echo "Error: " . $err;}
require 'net/http'require 'uri'url = URI('https://api.canva.com/rest/v1/generations')http = Net::HTTP.new(url.host, url.port)http.use_ssl = truerequest = Net::HTTP::Post.new(url)request['Authorization'] = 'Bearer {token}'request['Content-Type'] = 'application/json'request.body = <<REQUEST_BODY{"brief": "A 3-slide pitch deck for a solar-panel startup with an energetic, modern, blue-and-white visual direction.","design_type": {},"outline": {},"images": ["Msd59349ff"],"brand_templates": ["EDMzWSwy3BI"]}REQUEST_BODYresponse = http.request(request)puts response.read_body
Success response
If successful, the endpoint returns a 200 response with a JSON body with the following parameters:
jobDesignGenerationJobV2The status and result of a public design generation job.
idstringThe public design generation job ID.
statusstringThe public status of the job. result is present only for success, and
error is present only for failed.
Available values:
failed: The design couldn't be generated.in_progress: The design is still being generated.success: The design was generated and saved to the user's Canva account.
resultDesignGenerationJobResultV2Present only when the job status is success.
designDesignSummaryBasic details about the design, such as the design's ID, title, and URL.
idstringThe design ID.
urlsDesignLinksA temporary set of URLs for viewing or editing the design.
edit_urlstringA temporary editing URL for the design. This URL is only accessible to the user that made the API request, and is designed to support return navigation workflows.
This is not a permanent URL, it is only valid for 30 days.
view_urlstringA temporary viewing URL for the design. This URL is only accessible to the user that made the API request, and is designed to support return navigation workflows.
This is not a permanent URL, it is only valid for 30 days.
created_atintegerWhen the design was created in Canva, as a Unix timestamp (in seconds since the Unix Epoch).
updated_atintegerWhen the design was last updated in Canva, as a Unix timestamp (in seconds since the Unix Epoch).
titlestringThe design title.
urlstringURL of the design.
thumbnailThumbnailA thumbnail image representing the object.
widthintegerThe width of the thumbnail image in pixels.
heightintegerThe height of the thumbnail image in pixels.
urlstringA URL for retrieving the thumbnail image. This URL expires after 15 minutes. This URL includes a query string that's required for retrieving the thumbnail.
page_countintegerThe total number of pages in the design. Some design types don't have pages (for example, Canva docs).
errorDesignGenerationJobErrorV2Details about a failed design generation job.
codestringThe reason the design generation job failed.
Available values:
content_not_allowed: The brief or generated content didn't pass Canva's content-safety checks.generation_failed: Canva couldn't complete the design generation job.
messagestringA human-readable description of what went wrong.
quota_usageobjectCredit quota usage after reserving credits for this job. Omitted if unavailable.
Example response
Accepted job with available credit quota information
{"job": {"id": "f81b26fd-a33d-4c2d-9e8c-4a7aca798b17","status": "in_progress"},"quota_usage": {"used_percentage": 25,"resets_at": 1789257600,"using_bonus_credits": false}}
Error responses
400 Bad Request
codestringA short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses.
messagestringA human-readable description of what went wrong.
Example error responses
The request contains an invalid field
{"code": "invalid_field","message": "The presentation outline can only be used with the presentation design type."}
An attachment is invalid or unsupported
{"code": "invalid_field","message": "The specified attachment must identify a supported image or brand template."}
Too many generation inputs
{"code": "invalid_field","message": "At most 20 inputs are allowed across images and brand_templates combined."}
The design type isn't supported for generation
{"code": "invalid_field","message": "Design generation supports doc, presentation, and whiteboard presets."}
401 Unauthorized
codestringA short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses.
messagestringA human-readable description of what went wrong.
Example error responses
The OAuth client credentials are invalid
{"code": "invalid_client","message": "Client {clientId} not available"}
Access token could not be decoded or signature could not be verified.
{"code": "invalid_access_token","message": "Access token is invalid"}
Client credentials or body auth are missing from the request
{"code": "invalid_client","message": "Client credentials or body auth are missing from the request."}
Authorization header has wrong number of components
{"code": "invalid_access_token","message": "Malformed Authorization header: wrong number of components"}
Authorization header has invalid mode
{"code": "invalid_access_token","message": "Malformed Authorization header: invalid mode"}
Token couldn't be introspected
{"code": "invalid_access_token","message": "Token couldn't be introspected"}
Access token is revoked
{"code": "revoked_access_token","message": "Access token is revoked"}
Missing Authorization header
{"code": "invalid_access_token","message": "Missing Authorization header"}
Malformed Authorization header
{"code": "invalid_access_token","message": "Malformed Authorization header"}
403 Forbidden
codestringA short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses.
messagestringA human-readable description of what went wrong.
Example error responses
Design generation isn't available to the user
{"code": "permission_denied","message": "Design generation isn't available for this user."}
The user can't access an attachment
{"code": "permission_denied","message": "The user doesn't have access to the specified attachment."}
404 Not Found
codestringA short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses.
messagestringA human-readable description of what went wrong.
Example error response
An attachment wasn't found
{"code": "not_found","message": "The specified attachment wasn't found."}
429 Credit Quota Exceeded
codestringA short string indicating what failed. This field can be used to handle errors programmatically. For a complete list of error codes, see Error responses.
messagestringA human-readable description of what went wrong.
quota_usageobjectCredit quota usage at the time of the error. Not present if quota data is unavailable.
Example error responses
User has reached their credit quota limit
{"code": "credit_quota_exceeded","message": "User has exceeded their credit quota","quota_usage": {"used_percentage": 100,"resets_at": 1735689600,"using_bonus_credits": false,"upgrade_url": "https://www.canva.com/upgrade","is_admin": false,"generation_pending": false}}
User is in a cooldown period after heavy credit usage
{"code": "credit_quota_cooldown","message": "Credit quota cooldown is active","quota_usage": {"used_percentage": 100,"resets_at": 1735689600,"using_bonus_credits": false,"upgrade_url": "https://www.canva.com/upgrade","cooldown_ends_at": 1767182400,"is_admin": false,"generation_pending": true}}