Start MFA enrollment
Generates a TOTP secret, persists it encrypted with mfa_enabled still false, and returns otpauth_url plus Base32 secret for manual entry.
The SPA should render a QR code from otpauth_url locally. 409 if MFA is already fully enabled.
curl -X POST "https://slugbase.app/api/auth/mfa/enroll/begin" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN (JWT or sb_ API token)"
import requests
import json
url = "https://slugbase.app/api/auth/mfa/enroll/begin"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN (JWT or sb_ API token)"
}
response = requests.post(url, headers=headers)
print(response.json())
const response = await fetch("https://slugbase.app/api/auth/mfa/enroll/begin", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN (JWT or sb_ API token)"
}
});
const data = await response.json();
console.log(data);
package main
import (
"fmt"
"net/http"
)
func main() {
req, err := http.NewRequest("POST", "https://slugbase.app/api/auth/mfa/enroll/begin", nil)
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN (JWT or sb_ API token)")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status)
}
require 'net/http'
require 'json'
uri = URI('https://slugbase.app/api/auth/mfa/enroll/begin')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request['Authorization'] = 'Bearer YOUR_API_TOKEN (JWT or sb_ API token)'
response = http.request(request)
puts response.body
{
"otpauth_url": "example_string",
"secret": "example_string"
}
{
"error": "Unauthorized",
"message": "Authentication required. Please provide a valid API token",
"code": 401
}
{
"error": "Conflict",
"message": "The request conflicts with the current state of the resource",
"code": 409,
"details": "Resource already exists"
}
{
"error": "Too Many Requests",
"message": "Rate limit exceeded. Please try again later",
"code": 429,
"retryAfter": 3600
}
/api/auth/mfa/enroll/begin
Use Authorization: Bearer <token>. Personal API tokens from Profile use the sb_ prefix.
You may also send the access JWT as Bearer (same value as the token cookie after login).
Authorization: Bearer <token>. Personal API tokens from Profile use the sb_ prefix.
You may also send the access JWT as Bearer (same value as the token cookie after login).
Request Preview
Response
Response will appear here after sending the request
Authentication
Bearer token (JWT or sb_ API token). Use Authorization: Bearer \<token\>. Personal API tokens from Profile use the sb_ prefix.
You may also send the access JWT as Bearer (same value as the token cookie after login).
Responses
otpauth URI for QR / authenticator import (do not log in production)
Base32 secret for manual entry
Stable machine-readable codes include:
MFA_ALREADY_ENABLED, INVALID_CODE, MFA_PENDING_INVALID, MFA_NO_PENDING,
MFA_NOT_ENABLED, PASSWORD_REQUIRED, INVALID_PASSWORD.
Rate limited
Last updated Apr 17, 2026
Built with Documentation.AI