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"
}
| Status | Meaning |
|---|---|
| 400 | Invalid request body or missing required fields |
| 401 | Invalid or expired enrollment token |
| 429 | Rate limit exceeded (check Retry-After header) |
| 500 | Internal server error |
| 503 | Certificate 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"
}
| Field | Required | Description |
|---|---|---|
enrollmentToken | Yes | Time-limited enrollment token generated from the admin dashboard or API |
deviceFingerprint | Yes | Unique device identifier generated by the extension |
browserType | Yes | Browser name: Chrome, Edge, Firefox, or Safari |
browserVersion | No | Browser version string |
osType | No | Operating system: Windows, macOS, Linux, ChromeOS |
osVersion | No | Operating system version |
extensionVersion | Yes | Surface 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"
}
| Field | Description |
|---|---|
clientCertificate | PEM-encoded ECDSA P-256 device certificate signed by the tenant's CA |
clientPrivateKey | PEM-encoded ECDSA P-256 private key for the device |
caCertificate | PEM-encoded CA certificate for mTLS trust chain |
deviceId | UUID of the newly registered device |
userId | UUID of the associated user (may be an auto-created placeholder) |
expiresAt | Certificate expiration date (RFC 3339, typically 365 days from enrollment) |
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"
}
}
| Field | Required | Description |
|---|---|---|
username | Yes | Local or domain username |
upn | Yes | User Principal Name (email-style identifier) |
domain | No | Windows domain name |
sid | No | Windows Security Identifier |
displayName | No | User display name |
tenantId | Yes | Tenant UUID |
deviceInfo | No | Device 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 Code | Description |
|---|---|
missing_tenant | Tenant context not provided |
service_unavailable | Certificate service not configured |
user_not_found | User not found in synced directory |
invalid_request | Invalid request body |
Enrollment Flow
Manual Enrollment (Token-Based)
- An administrator generates an enrollment token in the dashboard (Settings > Onboarding) or via
POST /api/v1/admin/enrollment/token - The token is distributed to end users (email, documentation, or managed storage for enterprise deployments)
- The browser extension collects a device fingerprint and browser metadata
- The extension calls
POST /api/v1/enroll/certificatewith the token and device info - The backend validates the token, generates an ECDSA P-256 keypair, and issues a signed certificate
- The backend returns the signed certificate, private key, and CA certificate
- 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:
- The native messaging host is deployed via Intune, GPO, or MDM
- When the extension starts, it communicates with the native host via Chrome Native Messaging
- The native host authenticates the user via Windows (Kerberos/NTLM) or macOS (Keychain) identity
- The native host calls
POST /api/v1/enroll/autowith the authenticated user's identity - The backend matches the identity to a directory-synced user and issues credentials
- 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
| Limit | Default | Environment Variable |
|---|---|---|
| Requests per window | 3,000 per 60 seconds | ENROLL_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=5000or 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