Create Custom Enrollment Tickets

If you want to customize and manage your users' Multi-Factor Authentication (MFA) enrollments, you can use Custom Enrollment Tickets. Auth0's Custom Enrollment Tickets generate a single-use link to direct your users to enroll in MFA with the factor(s) you specify.

Use cases

Use Custom Enrollment Tickets for:

  • Onboarding new users

  • Configuring user settings

  • Specifying factors you want customers to choose during enrollment

  • Allowing users to enroll more than one factor

Configure Custom Enrollment Tickets

Make a post call to Management API's /guardian/post_ticket endpoint.


curl --request POST \
  --url 'https://{yourDomain}/api/v2/guardian/post-ticket' \
  --header 'authorization: Bearer {yourMgmtApiAccessToken}' \
  --header 'content-type: application/json' \
  --data '{ 
 "user_id": "string",
 "email": "user@exampleco.com",
 "send_email": "true",
 "email_locale": "string",
 "factor": "oob",
 "allow_multiple_enrollments": "true"
 }'

Was this helpful?

/
var client = new RestClient("https://{yourDomain}/api/v2/guardian/post-ticket");
var request = new RestRequest(Method.POST);
request.AddHeader("authorization", "Bearer {yourMgmtApiAccessToken}");
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", "{ \n \"user_id\": \"string\",\n \"email\": \"user@exampleco.com\",\n \"send_email\": \"true\",\n \"email_locale\": \"string\",\n \"factor\": \"oob\",\n \"allow_multiple_enrollments\": \"true\"\n }", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

Was this helpful?

/
package main

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

func main() {

	url := "https://{yourDomain}/api/v2/guardian/post-ticket"

	payload := strings.NewReader("{ \n \"user_id\": \"string\",\n \"email\": \"user@exampleco.com\",\n \"send_email\": \"true\",\n \"email_locale\": \"string\",\n \"factor\": \"oob\",\n \"allow_multiple_enrollments\": \"true\"\n }")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("authorization", "Bearer {yourMgmtApiAccessToken}")
	req.Header.Add("content-type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}

Was this helpful?

/
HttpResponse<String> response = Unirest.post("https://{yourDomain}/api/v2/guardian/post-ticket")
  .header("authorization", "Bearer {yourMgmtApiAccessToken}")
  .header("content-type", "application/json")
  .body("{ \n \"user_id\": \"string\",\n \"email\": \"user@exampleco.com\",\n \"send_email\": \"true\",\n \"email_locale\": \"string\",\n \"factor\": \"oob\",\n \"allow_multiple_enrollments\": \"true\"\n }")
  .asString();

Was this helpful?

/
var axios = require("axios").default;

var options = {
  method: 'POST',
  url: 'https://{yourDomain}/api/v2/guardian/post-ticket',
  headers: {
    authorization: 'Bearer {yourMgmtApiAccessToken}',
    'content-type': 'application/json'
  },
  data: {
    user_id: 'string',
    email: 'user@exampleco.com',
    send_email: 'true',
    email_locale: 'string',
    factor: 'oob',
    allow_multiple_enrollments: 'true'
  }
};

axios.request(options).then(function (response) {
  console.log(response.data);
}).catch(function (error) {
  console.error(error);
});

Was this helpful?

/
#import <Foundation/Foundation.h>

NSDictionary *headers = @{ @"authorization": @"Bearer {yourMgmtApiAccessToken}",
                           @"content-type": @"application/json" };
NSDictionary *parameters = @{ @"user_id": @"string",
                              @"email": @"user@exampleco.com",
                              @"send_email": @"true",
                              @"email_locale": @"string",
                              @"factor": @"oob",
                              @"allow_multiple_enrollments": @"true" };

NSData *postData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:nil];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://{yourDomain}/api/v2/guardian/post-ticket"]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
[request setHTTPMethod:@"POST"];
[request setAllHTTPHeaderFields:headers];
[request setHTTPBody:postData];

NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                if (error) {
                                                    NSLog(@"%@", error);
                                                } else {
                                                    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                                    NSLog(@"%@", httpResponse);
                                                }
                                            }];
[dataTask resume];

Was this helpful?

/
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://{yourDomain}/api/v2/guardian/post-ticket",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{ \n \"user_id\": \"string\",\n \"email\": \"user@exampleco.com\",\n \"send_email\": \"true\",\n \"email_locale\": \"string\",\n \"factor\": \"oob\",\n \"allow_multiple_enrollments\": \"true\"\n }",
  CURLOPT_HTTPHEADER => [
    "authorization: Bearer {yourMgmtApiAccessToken}",
    "content-type: application/json"
  ],
]);

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

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

Was this helpful?

/
import http.client

conn = http.client.HTTPSConnection("")

payload = "{ \n \"user_id\": \"string\",\n \"email\": \"user@exampleco.com\",\n \"send_email\": \"true\",\n \"email_locale\": \"string\",\n \"factor\": \"oob\",\n \"allow_multiple_enrollments\": \"true\"\n }"

headers = {
    'authorization': "Bearer {yourMgmtApiAccessToken}",
    'content-type': "application/json"
    }

conn.request("POST", "/{yourDomain}/api/v2/guardian/post-ticket", payload, headers)

res = conn.getresponse()
data = res.read()

print(data.decode("utf-8"))

Was this helpful?

/
require 'uri'
require 'net/http'
require 'openssl'

url = URI("https://{yourDomain}/api/v2/guardian/post-ticket")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

request = Net::HTTP::Post.new(url)
request["authorization"] = 'Bearer {yourMgmtApiAccessToken}'
request["content-type"] = 'application/json'
request.body = "{ \n \"user_id\": \"string\",\n \"email\": \"user@exampleco.com\",\n \"send_email\": \"true\",\n \"email_locale\": \"string\",\n \"factor\": \"oob\",\n \"allow_multiple_enrollments\": \"true\"\n }"

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

Was this helpful?

/
import Foundation

let headers = [
  "authorization": "Bearer {yourMgmtApiAccessToken}",
  "content-type": "application/json"
]
let parameters = [
  "user_id": "string",
  "email": "user@exampleco.com",
  "send_email": "true",
  "email_locale": "string",
  "factor": "oob",
  "allow_multiple_enrollments": "true"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://{yourDomain}/api/v2/guardian/post-ticket")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()

Was this helpful?

/

Parameter Required Description
allow_multiple_enrollments Optional Allows a previously enrolled user to enroll with additional factors, excluding email.
factor Optional Specifies which factor the user must enroll with, excluding email. Used with allow_multiple_enrollments, can specify more than one factor for enrollment.

Management API returns an enrollment ticket containing a ticket_id and a ticket_url. The ticket_id is for internal use. Deliver the ticket_url to the user with the send_email parameter to kick off the enrollment process. Tickets expire after 5 days and are single-use. A user who receives a ticket will only be able to enroll once.

Sample response:

{
  "ticket_id": "gten_8b2f5e90d2c848dc9230d34f",
  "ticket_url": "https://guardianadnrdoifcmtest0.eu.auth0.com/guardian/enroll?ticket=gten_8b2f5e90d2c848dc9230d34f"
}

Was this helpful?

/

If you enable Multiple Custom Domains, you need to include the auth0-custom-domain HTTP header. To learn more, review Multiple Custom Domains.

Custom Enrollment Tickets with Classic Login

If you are using the Classic Login experience and need to customize how the page looks when the user navigates to the ticket_url, you can edit the MFA page.

  1. Navigate to Dashboard > Branding > Universal Login > Advanced options > Multi-factor Authentication.

  2. If Customize MFA Page is not selected, toggle this option on.

  3. Update the ticket variable. Example:

{% if ticket %}
<h4 class="message">Welcome, {{ userData.email }}, enroll your device below</h4>
{% else %}
<h4 class="message">Welcome back, {{ userData.email }}, authenticate below</h4>
{% endif %}

Was this helpful?

/

Learn more