Skip to main content

Enrollment API

The Enrollment API handles device registration and certificate provisioning for browser extensions. Endpoints are under the /api/v1/enroll prefix.

Rate Limit: 3,000 requests per 60 seconds per client IP (configurable via ENROLL_RATE_LIMIT_RPS). For large deployments enrolling 5,000+ devices, increase this value or stagger enrollment across multiple waves. See Environment Variables for details.

Common Error Response

{
"error": "descriptive error message"
}
StatusMeaning
400Invalid request body or missing required fields
401Invalid or expired enrollment token
429Rate limit exceeded (check Retry-After header)
500Internal server error
503Certificate service not configured

Enroll Device

POST /api/v1/enroll/certificate

Enrolls a new device and issues a device certificate and private key for mTLS communication.

Headers: X-Tenant-ID (required)

Body:

{
"enrollmentToken": "enrollment-token-from-dashboard",
"deviceFingerprint": "unique-device-fingerprint",
"browserType": "Chrome",
"browserVersion": "120.0.6099.130",
"osType": "Windows",
"osVersion": "11",
"extensionVersion": "1.0.0"
}
FieldRequiredDescription
enrollmentTokenYesTime-limited enrollment token generated from the admin dashboard or API
deviceFingerprintYesUnique device identifier generated by the extension
browserTypeYesBrowser name: Chrome, Edge, Firefox, or Safari
browserVersionNoBrowser version string
osTypeNoOperating system: Windows, macOS, Linux, ChromeOS
osVersionNoOperating system version
extensionVersionYesSurface Security extension version

Response:

{
"clientCertificate": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
"clientPrivateKey": "-----BEGIN EC PRIVATE KEY-----\n...\n-----END EC PRIVATE KEY-----",
"caCertificate": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
"deviceId": "550e8400-e29b-41d4-a716-446655440000",
"userId": "550e8400-e29b-41d4-a716-446655440001",
"expiresAt": "2027-03-11T00:00:00Z"
}
FieldDescription
clientCertificatePEM-encoded ECDSA P-256 device certificate signed by the tenant's CA
clientPrivateKeyPEM-encoded ECDSA P-256 private key for the device
caCertificatePEM-encoded CA certificate for mTLS trust chain
deviceIdUUID of the newly registered device
userIdUUID of the associated user (may be an auto-created placeholder)
expiresAtCertificate expiration date (RFC 3339, typically 365 days from enrollment)
note

The server generates the ECDSA P-256 keypair during enrollment and returns both the certificate and private key. The private key is transmitted over TLS and is not retained by the server after issuance. The extension stores the certificate and private key locally for subsequent mTLS authentication.


Auto-Enroll (Enterprise)

POST /api/v1/enroll/auto

Handles automatic enrollment from the native companion app for enterprise deployments. The native host authenticates the user via Windows (Kerberos/NTLM) or macOS (Keychain) identity, removing the need for manual enrollment tokens.

Headers: X-Tenant-ID (required)

Body:

{
"username": "jsmith",
"upn": "jsmith@contoso.com",
"domain": "CONTOSO",
"sid": "S-1-5-21-...",
"displayName": "Jane Smith",
"tenantId": "uuid",
"deviceInfo": {
"hostname": "DESKTOP-ABC123",
"osType": "Windows",
"osVersion": "11",
"agentVersion": "1.0.0"
}
}
FieldRequiredDescription
usernameYesLocal or domain username
upnYesUser Principal Name (email-style identifier)
domainNoWindows domain name
sidNoWindows Security Identifier
displayNameNoUser display name
tenantIdYesTenant UUID
deviceInfoNoDevice metadata object

Response (success):

{
"success": true,
"userId": "uuid",
"accessKey": "access-key-for-extension",
"deviceId": "uuid",
"certificateData": "base64-encoded-certificate-bundle"
}

Response (error):

{
"success": false,
"error": "user not found in directory",
"errorCode": "user_not_found"
}
Error CodeDescription
missing_tenantTenant context not provided
service_unavailableCertificate service not configured
user_not_foundUser not found in synced directory
invalid_requestInvalid request body

Enrollment Flow

Manual Enrollment (Token-Based)

  1. An administrator generates an enrollment token in the dashboard (Settings > Onboarding) or via POST /api/v1/admin/enrollment/token
  2. The token is distributed to end users (email, documentation, or managed storage for enterprise deployments)
  3. The browser extension collects a device fingerprint and browser metadata
  4. The extension calls POST /api/v1/enroll/certificate with the token and device info
  5. The backend validates the token, generates an ECDSA P-256 keypair, and issues a signed certificate
  6. The backend returns the signed certificate, private key, and CA certificate
  7. The extension stores the credentials locally and begins mTLS-authenticated communication

Enterprise Auto-Enrollment

For deployments using Intune or GPO, automatic enrollment is supported through a native companion app:

  1. The native messaging host is deployed via Intune, GPO, or MDM
  2. When the extension starts, it communicates with the native host via Chrome Native Messaging
  3. The native host authenticates the user via Windows (Kerberos/NTLM) or macOS (Keychain) identity
  4. The native host calls POST /api/v1/enroll/auto with the authenticated user's identity
  5. The backend matches the identity to a directory-synced user and issues credentials
  6. No manual enrollment token is required

See the Extension Deployment Guide for details on configuring managed storage and native messaging hosts.

Token Expiration

Enrollment tokens default to expiring at the tenant's license expiration date. Administrators can request a shorter window by passing expiresInDays when generating the token (POST /api/v1/admin/enrollment/token); values that would extend beyond the license expiry are clamped to the license expiry. Tokens are single-use and are invalidated after a successful enrollment.

Rate Limiting

LimitDefaultEnvironment Variable
Requests per window3,000 per 60 secondsENROLL_RATE_LIMIT_RPS

The enrollment endpoint uses a separate, higher rate limit than the general API to accommodate large-scale rollouts where many devices enroll from the same corporate network (NAT IP).

When rate limited, responses include a Retry-After header indicating seconds until the window resets.

Guidance for large deployments:

  • For 5,000+ devices: set ENROLL_RATE_LIMIT_RPS=5000 or higher
  • For 10,000+ devices: consider staggering enrollment across multiple waves
  • If enrolling from multiple egress IPs, each IP gets its own rate limit budget