REST: Auth and Account
The authentication and account-management routes under buddynext/v1. They cover front-end login, registration, two-factor verification, email verification, member approval, and the self-service account flows (change password, change email, sign out everywhere, manage 2FA, mint/revoke application passwords, and unlink social providers). This page is for developers building a custom login UI, a mobile client, or any client that drives these flows over REST.

Contract
Section titled “Contract”These routes follow the same envelope, error shape, and nonce rules as the rest of the API - see the REST contract page (14-rest-contract) for the cross-surface conventions. Two things are specific to this surface:
- Permission model is unusual here. Most BuddyNext routes gate on a capability or login state. The auth routes intentionally do not: the pre-login routes are public (
permission_callback => __return_true) because the caller has no session yet. The account routes and the post-login auth routes gate on “logged in” only. Per-route detail is in the tables below. - Authenticated calls still need the cookie +
wp_restnonce. “Public” means no capability check, not “no authentication needed for state to be correct”. A logged-in client calls these with the standardX-WP-Nonceheader. If the nonce goes stale, mint a fresh one fromGET /auth/nonce(see Notes).
Source: includes/Auth/AuthController.php (auth + app-password routes), includes/Auth/TwoFactorController.php (account/2fa routes), and includes/Auth/SocialLogin.php (the social-unlink route).
Auth routes
Section titled “Auth routes”All paths below are prefixed with /wp-json/buddynext/v1.
| Method | Path | Auth | Purpose |
|---|---|---|---|
| POST | /auth/login |
Public | Log a user in by email/username + password. Returns a 2FA challenge token instead of a session when 2FA is enabled. |
| POST | /auth/2fa |
Public | Complete a 2FA challenge with twofa_token + code, finishing the login. |
| POST | /auth/2fa/email-code |
Public | Send a one-time 2FA code by email for the pending challenge (twofa_token). |
| GET | /auth/register/config |
Public | The signup contract plus a fresh guard bundle. Call this before /auth/register. See below. |
| POST | /auth/register |
Public | Create a new user account (email, user_login, password, optional terms_agreed, invite). |
| POST | /auth/register/complete |
Public | Finish a parked social sign-up: supply pending_token plus the things OAuth cannot (terms_agreed, required profile fields), then the account is created. |
| POST | /auth/lost-password |
Public | Start a password reset for user_login (email or username). |
| POST | /auth/reset-password |
Public | Complete a reset with key + login + new password. |
| POST | /auth/approve/{id} |
Admin | Approve a pending member (manual-approval registration mode). |
| POST | /auth/verify/resend |
Logged in | Resend the email-verification message for the current user. |
| GET | /auth/verify/status |
Logged in | Return the current user’s email-verification status. |
| POST | /auth/change-password |
Logged in | Set a new password after verifying current_password. Returns 422 with field-keyed errors on failure. |
| POST | /auth/change-email |
Logged in | Change the current user’s email (email). |
| POST | /auth/sign-out-everywhere |
Logged in | Destroy all of the current user’s sessions on every device. |
| POST | /auth/app-password |
Logged in | Mint a WordPress Application Password for the current user (optional name). The plaintext password is returned once (201). |
| GET | /auth/app-password |
Logged in | List the current user’s Application Passwords (metadata only, never the secret). |
| DELETE | /auth/app-password/{uuid} |
Logged in | Revoke one of the current user’s Application Passwords. |
| GET | /auth/nonce |
Public | Mint a fresh wp_rest nonce for the current session (stale-nonce recovery). |
The login, register, 2FA, lost-password, and reset-password routes register with
permission_callback => __return_true. They are reachable by anyone, by design, because the caller is pre-session./auth/approve/{id}checks an admin capability in its own callback; the verify/change/sign-out routes checkrequire_auth(logged in).
GET /auth/register/config - read this before you register
Section titled “GET /auth/register/config - read this before you register”A non-browser client (a native app, a headless front end) cannot register without calling this first. The anti-bot guard bundle - the time-trap token, the human-check question, the honeypot field name - is otherwise only minted inside the signup template. A client that posts straight to /auth/register without those values is scored as a bot and rejected.
The route is public and returns the signup contract plus a freshly minted guard bundle:
| Key | Type | Meaning |
|---|---|---|
mode |
string |
The site’s registration mode. |
terms |
bool |
Whether terms consent is required. |
terms_url |
string |
Where the terms document lives. |
fields |
array |
The required profile fields, each { key, label, type, required, options, description }. |
reg_token |
string |
The time-trap token. Post it back on /auth/register. |
honeypot_field |
string |
The name of the honeypot input. Send it empty. |
challenge |
array |
{ question, token } when the human check is enabled; an empty array when it is not. |
Mint the bundle fresh per signup attempt - the tokens are single-use.
POST /auth/register/complete - finish a parked social sign-up
Section titled “POST /auth/register/complete - finish a parked social sign-up”An OAuth provider can hand back an identity but not terms consent, and not the site’s required profile fields. When that happens the sign-up is parked rather than failed, and the client is given a pending_token. Post it back here with terms_agreed and the outstanding fields, and the account is created.
Account (2FA) routes
Section titled “Account (2FA) routes”Two-factor enrollment and management for the signed-in user. Every route here requires login (require_auth); there is no public or capability variant.
| Method | Path | Auth | Purpose |
|---|---|---|---|
| GET | /account/2fa |
Logged in | Return the current user’s 2FA status (enabled, method, backup-codes remaining). |
| POST | /account/2fa/setup |
Logged in | Begin TOTP enrollment; returns the secret/QR provisioning data to confirm against. |
| POST | /account/2fa/confirm |
Logged in | Confirm enrollment with a code from the authenticator app, activating 2FA. |
| POST | /account/2fa/disable |
Logged in | Disable 2FA after re-verifying the account password. |
| POST | /account/2fa/backup |
Logged in | Regenerate backup codes after re-verifying the account password. |
Social account linking
Section titled “Social account linking”Social login itself runs over browser rewrite routes (/oauth/{provider}/ and /oauth/{provider}/callback/), not JSON REST. The one REST route on this surface unlinks a provider from the signed-in user.
| Method | Path | Auth | Purpose |
|---|---|---|---|
| DELETE | /me/social/{provider} |
Logged in | Unlink a linked social provider (e.g. google, facebook, github, discord) from the current user. Returns {"unlinked": true}. |
Examples
Section titled “Examples”Log in
Section titled “Log in”A successful login with 2FA off returns the session result. With 2FA on, the response carries a twofa_token and the client must follow up with POST /auth/2fa.
curl -X POST https://example.com/wp-json/buddynext/v1/auth/login \ -H 'Content-Type: application/json' \ -d '{ "user": "ada@example.com", "password": "correct horse battery staple", "remember": true }'Parameters: user (required, email or username), password (required), remember (optional boolean, default false). When the account has 2FA enabled, complete the challenge:
curl -X POST https://example.com/wp-json/buddynext/v1/auth/2fa \ -H 'Content-Type: application/json' \ -d '{ "twofa_token": "<token-from-login>", "code": "123456" }'Register
Section titled “Register”curl -X POST https://example.com/wp-json/buddynext/v1/auth/register \ -H 'Content-Type: application/json' \ -d '{ "email": "grace@example.com", "user_login": "grace", "password": "a strong passphrase", "terms_agreed": true, "invite": "ABCD-1234" }'Required: email, user_login, password. Optional: terms_agreed (boolean, default false), invite (string, used when the community runs invite-gated or referral registration). Registration honours the site’s users_can_register setting and the configured approval mode - when manual approval is on, the new account stays pending until an admin calls POST /auth/approve/{id}.
Change password (validation envelope)
Section titled “Change password (validation envelope)”State-changing account calls send the cookie + nonce and return field-keyed 422 errors on validation failure:
curl -X POST https://example.com/wp-json/buddynext/v1/auth/change-password \ -H 'Content-Type: application/json' \ -H 'X-WP-Nonce: <wp_rest nonce>' \ --cookie 'wordpress_logged_in_...=...' \ -d '{ "current_password": "old-pass", "new_password": "new-pass-8+chars" }'{ "code": "rest_invalid_param", "message": "Current password does not match.", "data": { "status": 422, "fields": { "current_password": "Current password does not match." } }}- Stale-nonce recovery.
GET /auth/noncemints a freshwp_restnonce for the current session and sendsCache-Control: no-store. The shared front-end REST client uses it to recover from a 403 on a stale nonce without a full page reload. It re-validates the auth cookie directly, so it never returns an anonymous nonce to a logged-in caller, and the minted nonce is usable only by the same session. - 2FA login is a two-step flow.
POST /auth/logindoes not always return a session - if the account has 2FA on, it returns atwofa_token. The client then callsPOST /auth/2fa(TOTP/backup code) or requests an email code first viaPOST /auth/2fa/email-code. Build clients to expect either outcome. - Re-authentication on sensitive 2FA changes. Disabling 2FA and regenerating backup codes both require the account
passwordin the request body, not just an active session. - Free vs Pro. All routes on this page are part of Free (
buddynext/v1). Pro adds its own account-scoped routes underbuddynext-pro/v1(billing, subscriptions, push preferences) - see REST: Pro namespace (24-rest-pro).

