Skip to content

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-Nonce required 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.marketingOptIn stores a boolean (true/false) in the consent blob.
  • headlesswp_marketing_opt_in stores 'yes' or 'no' as explicit user meta for WP admin visibility.
  • headlesswp_marketing_opt_in_at stores 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|no
    • Customer marketing opt-in at: <ISO or ->
    • Partner marketing opt-in: yes|no
    • Partner 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

StatusCodeNotes
400AUTH_REGISTRATION_FAILEDAccount creation failed.
400PASSWORD_POLICY_VIOLATIONPassword did not meet policy requirements (error.details.reason = "password_policy").
403AUTH_REGISTRATION_DISABLEDRegistration is disabled.
403CSRF_FAILEDMissing or invalid nonce (error.details.reason is missing_nonce or invalid_nonce).
422VALIDATION_FAILEDField validation failed. error.details.fieldErrors includes per-field messages.
429AUTH_RATE_LIMITEDRegistration is rate limited (error.details.bucket).
500INTERNAL_SERVER_ERRORAuto-login failed after registration.

Rate limiting

Registration is rate limited by IP and by email address in the fixture implementation.