Register
id: core-auth-register owner: core method: POST path: /wp-json/headlesswp/v1/auth/register title: Register usedBySite: true
POST /wp-json/headlesswp/v1/auth/register
Create a new account and (when email verification is not required) start a cookie session.
Auth + CSRF
- Auth: public
- Proxy nonce required: yes.
- CSRF:
X-WP-Noncerequired by the proxy and by HWP (nonce policy: always). - Cookies: first-party cookies are set via the
/api/secure/**proxy response.
Request schema
{
"email": "string (required)",
"password": "string (required)",
"displayName": "string (required)",
"acceptTerms": "boolean (required, must be true)",
"firstName": "string (optional)",
"lastName": "string (optional)",
"marketingOptIn": "boolean (optional; missing/null treated as false)",
"termsAcceptedAt": "ISO8601 string (optional)",
"privacyAcceptedAt": "ISO8601 string (optional)"
}
firstName and lastName populate both the HeadlessWP registration profile meta and the WordPress core first_name/last_name user profile fields. Those values are surfaced by /me via data.profile.firstName and data.profile.lastName (with core-meta fallback when custom profile meta is absent).
marketingOptIn is persisted deterministically as yes/no:
headlesswp_consent_registration.marketingOptInstores a boolean (true/false) in the consent blob.headlesswp_marketing_opt_instores'yes'or'no'as explicit user meta for WP admin visibility.headlesswp_marketing_opt_in_atstores an ISO-8601 timestamp when opted in ('yes'); otherwise the timestamp meta is cleared.- The WordPress user bio (
description) is overwritten with a deterministic consent summary block visible in WP Admin > Users > Edit user > Biographical Info, including both customer and partner marketing consent values:Customer marketing opt-in: yes|noCustomer marketing opt-in at: <ISO or ->Partner marketing opt-in: yes|noPartner marketing opt-in at: <ISO or ->
Response schema
Two success variants are possible:
201 Created (email verification required)
{
"data": {
"user": "<user object>",
"flags": "<flags object>",
"entitlements": "<entitlements object>",
"registrationStatus": "pending_verification"
},
"meta": {
"correlationId": "string-or-null",
"correlation_id": "string-or-null",
"request_id": "string-or-null",
"timestamp": "2024-01-01T00:00:00Z",
"nextStep": "VERIFY_EMAIL",
"expiresAt": "2024-01-01T00:00:00Z"
}
}
201 Created (auto-login)
{
"data": {
"user": "<user object>",
"flags": "<flags object>",
"entitlements": "<entitlements object>",
"next": "/wp-json/headlesswp/v1/me"
},
"meta": {
"correlationId": "string-or-null",
"correlation_id": "string-or-null",
"request_id": "string-or-null",
"timestamp": "2024-01-01T00:00:00Z",
"nextStep": "NONE"
}
}
<user object>, <flags object>, and <entitlements object> follow the same shape as the login response.
Error codes
| Status | Code | Notes |
|---|---|---|
| 400 | AUTH_REGISTRATION_FAILED | Account creation failed. |
| 400 | PASSWORD_POLICY_VIOLATION | Password did not meet policy requirements (error.details.reason = "password_policy"). |
| 403 | AUTH_REGISTRATION_DISABLED | Registration is disabled. |
| 403 | CSRF_FAILED | Missing or invalid nonce (error.details.reason is missing_nonce or invalid_nonce). |
| 422 | VALIDATION_FAILED | Field validation failed. error.details.fieldErrors includes per-field messages. |
| 429 | AUTH_RATE_LIMITED | Registration is rate limited (error.details.bucket). |
| 500 | INTERNAL_SERVER_ERROR | Auto-login failed after registration. |
Rate limiting
Registration is rate limited by IP and by email address in the fixture implementation.