Initiate registration
AUTHENTICATED BY X-API-Key, not by a bearer token. auth.APIKeyMiddleware REPLACES the usual chain on this route, so there is no user context, no RBAC check and no licence check — and the refusals are common.api_key_required / common.invalid_api_key rather than common.unauthorized / common.rbac_no_rec_access. An OPTIONS request skips the key check entirely. Begin registration. The answer is deliberately uniform: the same `200` and the same message whether the credential is free, belongs to a registration nobody finished, or is already confirmed on another account. No code is sent for a credential somebody else holds, and no account is created for it; its owner is notified that an attempt was made. Send pacing applies either way, so a burst answers `429 otp_m.resend_too_soon` or `otp_m.resend_limit_exceeded` on any of those paths. `400` covers the request itself — a malformed or undeliverable credential, a password that fails policy, terms or privacy not accepted.
Authorization
apiKeyAuth Service API key for the eight pre-authentication user routes. auth.APIKeyMiddleware REPLACES the bearer chain on those routes rather than wrapping it: there is no user context, no RBAC check and no licence check on them.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/users/initiate-registration" \ -H "Content-Type: application/json" \ -d '{ "credential_type": "email", "credential_value": "string", "password": "string", "terms_accepted": true, "privacy_policy_accepted": true }'{
"message": "string"
}{
"status": 400,
"message": "Invalid user input",
"code": "users_m.invalid_user_input",
"class": "validation"
}{
"status": 401,
"message": "common.api_key_required",
"code": "common.api_key_required",
"class": "business"
}{
"status": 403,
"message": "common.invalid_api_key",
"code": "common.invalid_api_key",
"class": "business"
}{
"status": 429,
"message": "Too many activation attempts. Please try again in 842 seconds",
"code": "users_m.activation_rate_limit_exceeded",
"class": "temporary",
"retryable": true
}{
"status": 500,
"message": "Cache operation error",
"code": "otp_m.cache_error",
"class": "business"
}{
"overall_status": "unhealthy",
"message": "Service is shutting down",
"timestamp": "2026-08-27T15:04:05Z"
}Previous Page
AUTHENTICATED BY X-API-Key, not by a bearer token. auth.APIKeyMiddleware REPLACES the usual chain on this route, so there is no user context, no RBAC check and no licence check — and the refusals are common.api_key_required / common.invalid_api_key rather than common.unauthorized / common.rbac_no_rec_access. An OPTIONS request skips the key check entirely. Ask for the registration code again. One answer covers every outcome: a credential still waiting for its code is sent another, and a request that names an address nobody registered, one already confirmed, or an account with no credential is answered identically without sending anything. Send pacing applies to both, so a burst answers `429`. The endpoint is also rate limited per IP.