Create user
Creates a managed user in the caller's organization. The email domain must be a verified domain owned by the caller's organization, and the SAML identity provider (resolved by idp_issuer) must belong to that organization. If the email already belongs to an existing Canva account that isn't part of an organization, that account is brought into the organization rather than a new one being created; the person may be asked to confirm. If successful, the user's Canva ID, email, display name, first name, last name, and organization role are returned.
HTTP method and URL path
https://api.canva.com /admin /v1 /usersAuthentication and authorization
This endpoint requires a valid access token that was generated using client credentials.
Scopes
The access token must have all the following scopes (permissions):
admin:user:writeadmin:team:write
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
emailstringThe email address of the user. The email domain must be a verified domain owned by the caller's organization.
Minimum length: 1
Maximum length: 254
display_namestringThe display name of the user.
Minimum length: 1
saml_accountSamlAccountThe SAML account details used to link the user to the organization's identity provider for SSO.
idp_issuerstringThe issuer URL of the SAML identity provider. Must resolve to an identity provider owned by the caller's organization.
Minimum length: 1
name_idstringThe SAML NameID that identifies the user to the identity provider. Case sensitive, should not change.
Minimum length: 1
team_membershipsTeamMembership[]The teams the user is added to. At least one team membership is required so the user is visible via getUser and listUsers.
Minimum items: 1
team_idstringThe team ID.
rolestringThe role of the member in the team.
Available values:
admindesignermember
first_namestringThe first name of the user.
last_namestringThe last name of the user.
localestringThe locale of the user, as an IETF BCP 47 language tag. Must be a supported language. Defaults to en if not provided.
Default value: en
Example request
Examples for using the /v1/users endpoint:
curl --request POST 'https://api.canva.com/admin/v1/users' \--header 'Authorization: Bearer {token}' \--header 'Content-Type: application/json' \--data '{"email": "joe@acme.com","display_name": "Joe Smith","first_name": "Joe","last_name": "Smith","locale": "en","saml_account": {"idp_issuer": "https://sso.acme.com/saml/metadata","name_id": "joe.smith@acme.com"},"team_memberships": [{"team_id": "BAAAAAAAAA1","role": "member"}]}'
const fetch = require("node-fetch");fetch("https://api.canva.com/admin/v1/users", {method: "POST",headers: {"Authorization": "Bearer {token}","Content-Type": "application/json",},body: JSON.stringify({"email": "joe@acme.com","display_name": "Joe Smith","first_name": "Joe","last_name": "Smith","locale": "en","saml_account": {"idp_issuer": "https://sso.acme.com/saml/metadata","name_id": "joe.smith@acme.com"},"team_memberships": [{"team_id": "BAAAAAAAAA1","role": "member"}]}),}).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/admin/v1/users")).header("Authorization", "Bearer {token}").header("Content-Type", "application/json").method("POST", HttpRequest.BodyPublishers.ofString("{\"email\": \"joe@acme.com\", \"display_name\": \"Joe Smith\", \"first_name\": \"Joe\", \"last_name\": \"Smith\", \"locale\": \"en\", \"saml_account\": {\"idp_issuer\": \"https://sso.acme.com/saml/metadata\", \"name_id\": \"joe.smith@acme.com\"}, \"team_memberships\": [{\"team_id\": \"BAAAAAAAAA1\", \"role\": \"member\"}]}")).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 = {"email": "joe@acme.com","display_name": "Joe Smith","first_name": "Joe","last_name": "Smith","locale": "en","saml_account": {"idp_issuer": "https://sso.acme.com/saml/metadata","name_id": "joe.smith@acme.com"},"team_memberships": [{"team_id": "BAAAAAAAAA1","role": "member"}]}response = requests.post("https://api.canva.com/admin/v1/users",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/admin/v1/users"),Headers ={{ "Authorization", "Bearer {token}" },},Content = new StringContent("{\"email\": \"joe@acme.com\", \"display_name\": \"Joe Smith\", \"first_name\": \"Joe\", \"last_name\": \"Smith\", \"locale\": \"en\", \"saml_account\": {\"idp_issuer\": \"https://sso.acme.com/saml/metadata\", \"name_id\": \"joe.smith@acme.com\"}, \"team_memberships\": [{\"team_id\": \"BAAAAAAAAA1\", \"role\": \"member\"}]}",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(`{"email": "joe@acme.com","display_name": "Joe Smith","first_name": "Joe","last_name": "Smith","locale": "en","saml_account": {"idp_issuer": "https://sso.acme.com/saml/metadata","name_id": "joe.smith@acme.com"},"team_memberships": [{"team_id": "BAAAAAAAAA1","role": "member"}]}`)url := "https://api.canva.com/admin/v1/users"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/admin/v1/users",CURLOPT_CUSTOMREQUEST => "POST",CURLOPT_RETURNTRANSFER => true,CURLOPT_HTTPHEADER => array('Authorization: Bearer {token}','Content-Type: application/json',),CURLOPT_POSTFIELDS => json_encode(["email" => "joe@acme.com","display_name" => "Joe Smith","first_name" => "Joe","last_name" => "Smith","locale" => "en","saml_account" => ["idp_issuer" => "https://sso.acme.com/saml/metadata","name_id" => "joe.smith@acme.com"],"team_memberships" => [["team_id" => "BAAAAAAAAA1","role" => "member"]]])));$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/admin/v1/users')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{"email": "joe@acme.com","display_name": "Joe Smith","first_name": "Joe","last_name": "Smith","locale": "en","saml_account": {"idp_issuer": "https://sso.acme.com/saml/metadata","name_id": "joe.smith@acme.com"},"team_memberships": [{"team_id": "BAAAAAAAAA1","role": "member"}]}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:
userUserA user.
idstringThe user ID.
display_namestringThe display name of the user.
emailstringThe email address of the user.
first_namestringThe first name of the user.
last_namestringThe last name of the user.
last_active_atintegerWhen the user was last active, as a Unix timestamp (in seconds since the Unix Epoch).
localestringThe locale of the user, as an IETF BCP 47 language tag.
rolestringThe role of the user in the organization.
Available values:
adminbrand_designermember
Example response
{"user": {"id": "UAAAAAAAAA1","display_name": "Joe Smith","email": "joe@acme.com","first_name": "Joe","last_name": "Smith","last_active_at": 1750300000,"locale": "en","role": "admin"}}
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 response
The display name is not allowed
{"code": "invalid_field","message": "The supplied display_name is not allowed."}
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
The SAML identity provider is not owned by the caller's organization (or doesn't exist)
{"code": "permission_denied","message": "The identity provider is not owned by your organization."}
The email domain is not a verified domain owned by the caller's organization
{"code": "permission_denied","message": "The email domain is not in your organization's verified domains."}
A target team has reached its maximum member capacity
{"code": "max_limit_reached","message": "One or more provided teams have reached its maximum member capacity"}
409 Conflict
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 user matching the email is not active
{"code": "user_not_active","message": "The existing user matching this email is not active and can't be added."}
The user is awaiting consent from a previous request
{"code": "user_pending_consent","message": "A previous request for this user is awaiting their consent. Wait for them to accept before retrying."}
The SAML name ID is already in use
{"code": "saml_name_id_not_available","message": "The SAML name ID {nameId} is already associated with another user."}
An account already exists for this email
{"code": "account_exists","message": "That email address is already associated with a Canva account."}
The existing account's email is not verified
{"code": "user_email_unverified","message": "The existing account for this email hasn't verified its email address, so it can't be linked to your organization."}