Register (email + password)
Auth
Register (email + password)
Create a new Swappr account with email + password. Sends a 6-digit verification code.
POST
Register (email + password)
Overview
Starts a new registration from the Create account screen. The client collects the user’sfirstName, lastName, email, password, an optional dateOfBirth, and explicit termsAccepted + privacyAccepted consent (both must be true). Names should be entered exactly as they appear on the tenancy agreement, since they are later matched against the uploaded tenancy document.
On success the account is created with emailVerified: false, the profile + consent fields are persisted (consent timestamps recorded), and a 6-digit one-time verification code is sent to the supplied email via Resend. The client must then call POST /verify-email with the code to log the user in — this endpoint does NOT return tokens.
If the email is already registered with the same password, this is treated as an idempotent retry: a fresh verification code is dispatched and userId returns null. The response is intentionally identical to the new-account case so a caller cannot tell the email already existed.
If the email is registered with a different password the request is rejected with 409 EMAIL_ALREADY_REGISTERED. If the email is registered via OAuth (Google / Apple) the request is rejected with 409 ACCOUNT_EXISTS_VIA_OAUTH so the client can redirect to the appropriate sign-in flow.
Authentication
None required.Path parameters
None.Query parameters
None.Request body
| Field | Type | Required | Allowed values | Example |
|---|---|---|---|---|
firstName | string | yes | 1..100 chars after trim. Use the name as it appears on the tenancy agreement. | Alice |
lastName | string | yes | 1..100 chars after trim. | Smith |
email | string | yes | RFC 5322 valid, 5..254 chars, lowercased server-side | alice@example.com |
password | string | yes | 8..200 chars; must contain at least one letter AND one digit | p4ssword1 |
dateOfBirth | string | no | ISO calendar date YYYY-MM-DD; applicant must be 18 or older. Omit to skip. | 1990-06-15 |
termsAccepted | boolean | yes | Must be true — the user ticked “I agree to the Terms & Conditions”. | true |
privacyAccepted | boolean | yes | Must be true — the user ticked “I agree to the Privacy Policy”. | true |
Example payload
Response — 201 Created
| Field | Type | Notes | Example |
|---|---|---|---|
userId | string | null | The new user’s ID, or null on an idempotent retry. Clients must treat both as success. | usr_01HZQ7K3M4N5P6Q7R8S9T0V1W2 |
emailVerificationRequired | boolean | Always true for this endpoint. Hint to the client to prompt for the OTP. | true |
Example response
Error responses
| Status | Code | Meaning |
|---|---|---|
| 400 | VALIDATION_FAILED | Missing/blank firstName or lastName; email malformed; password too short or missing a letter/digit; dateOfBirth not YYYY-MM-DD or under 18; termsAccepted or privacyAccepted not true. |
| 409 | EMAIL_ALREADY_REGISTERED | The email exists with a different password. Use /login or /forgot-password. |
| 409 | ACCOUNT_EXISTS_VIA_OAUTH | The email is bound to a Google / Apple OAuth identity. Use the corresponding OAuth flow. |
| 503 | MAIL_NOT_CONFIGURED | Resend API key is missing in this environment. |
Example error — 409
Side effects
- Inserts a new row into the
userscollection withemailVerified: false, the suppliedfirstName/lastName/dateOfBirth, andtermsAccepted/privacyAcceptedset totruewith their acceptance timestamps (idempotent retry skips insert). - Inserts a row into the
otp_codescollection (purpose: 'email_verify', 5-min TTL). Any prior outstanding code for this email is invalidated. - Sends an email via Resend with the 6-digit code.
See also
- Verify email — confirm the OTP and receive tokens.
- Resend verification email — request a fresh code (60 s cooldown).
- Errors — full error code catalog.