Authentication
User Authentication
WoWSQL provides complete authentication for your application users. Enable auth in your project settings, then call these endpoints on your project host. Paths below are relative to the base URL. Send your anon key in the apikey header (the official SDKs do this for you).
Base URL: https://your-project-slug.wowsqlconnect.com/api/auth
The equivalent /auth/v1 prefix also works (for example /auth/v1/login); the gateway rewrites /api/auth/... to /auth/v1/....
User Registration
POST /signup
Headers:
Content-Type: application/json
Body:
{
"email": "user@example.com",
"password": "securepassword123",
"full_name": "John Doe",
"user_metadata": {
"company": "Acme Corp"
}
}
User Login
POST /login
Headers:
Content-Type: application/json
Body:
{
"email": "user@example.com",
"password": "securepassword123"
}
Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "refresh_token_here",
"user": {
"id": "user-id",
"email": "user@example.com",
"email_verified": true
}
}
If the user has two-factor authentication enabled, the response contains "requires_2fa": true and a pending_token instead of tokens; see Signing in when 2FA is enabled.
Get Current User
GET /me
Headers:
Authorization: Bearer ACCESS_TOKEN
OAuth Authentication
Allow users to sign in with Google, GitHub, and other providers. Provider setup, the full flow, identity linking, errors and SDK examples are in OAuth for Projects.
Supported {provider} values (20 in the dashboard): google, github, microsoft, azure, apple, facebook, twitter, discord, gitlab, linkedin, twitch, spotify, notion, slack, bitbucket, figma, zoom, kakao, keycloak and workos. microsoft and azure are separate entries that both use Microsoft sign-in. Use twitter for X; x is not a provider value. keycloak can be saved but cannot be used for sign-in yet, so 19 providers work today. A provider must be configured (client ID and secret) and enabled for the project; otherwise the request returns 400.
GET /oauth/{provider}?frontend_redirect_uri=https://yourapp.com/auth/callback
Headers:
apikey: YOUR_ANON_KEY
Response (JSON; the endpoint does not redirect):
{
"authorization_url": "https://accounts.google.com/o/oauth2/v2/auth?...",
"provider": "google",
"backend_callback_url": "https://your-project-slug.wowsqlconnect.com/auth/v1/oauth/google/callback",
"frontend_redirect_uri": "https://yourapp.com/auth/callback"
}
// Optional: frontend_redirect_uri (defaults to the project's Frontend URL)
// Send the user's browser to authorization_url.
// Callback: the provider returns to /oauth/{provider}/callback, which
// redirects to frontend_redirect_uri with access_token, refresh_token,
// token_type, expires_in, user_id and email in the query string.
To let a third-party app such as Zapier or n8n work with one of your WoWSQL projects (WoWSQL as the OAuth server), see Sign in with WoWSQL (OAuth Connect).
Magic Links (Passwordless)
Send passwordless login links via email:
POST /magic-link/send
Headers:
Content-Type: application/json
Body:
{
"email": "user@example.com"
}
// User clicks link in email
GET /magic-link/verify?token=VERIFICATION_TOKEN
Phone Number + OTP
SMS-based authentication:
POST /otp/send
Headers:
Content-Type: application/json
Body:
{
"phone": "+1234567890",
"purpose": "login"
}
POST /otp/verify
Body:
{
"phone": "+1234567890",
"otp": "123456",
"purpose": "login"
}
Phone numbers use E.164 format. For email OTP, send "email" instead of "phone". purpose is one of login, signup or password_reset (default login); for password_reset, also send new_password to /otp/verify.
Password Reset
POST /forgot-password
Headers:
Content-Type: application/json
Body:
{
"email": "user@example.com"
}
POST /reset-password
Body:
{
"token": "reset_token_from_email",
"new_password": "newsecurepassword123"
}
Email Verification
POST /verify-email
Headers:
Authorization: Bearer ACCESS_TOKEN
// Or verify via email link
GET /verify-email?token=VERIFICATION_TOKEN
Two-Factor Authentication
Add an extra layer of security with 2FA. Your app users can protect their accounts with a time-based one-time password (TOTP) from an authenticator app (Google Authenticator, 1Password, Authy and similar). All 2FA endpoints are under the same base URL (/api/auth/2fa/... or /auth/v1/2fa/...).
POST /2fa/setup-totp
Headers:
Authorization: Bearer ACCESS_TOKEN
// Returns the TOTP secret and a QR code for an authenticator app
Response:
{
"secret": "JBSWY3DPEHPK3PXP",
"otpauth_uri": "otpauth://totp/...",
"qr_code_uri": "otpauth://totp/...",
"qr_code_url": "data:image/png;base64,...",
"qr_code_png": "data:image/png;base64,..."
}
POST /2fa/verify-and-enable
Headers:
Authorization: Bearer ACCESS_TOKEN
Body:
{
"totp_code": "123456"
}
Response:
{
"success": true,
"message": "Two-factor authentication enabled",
"backup_codes": ["1a2b-3c4d", "..."],
"recovery_codes": ["1a2b-3c4d", "..."]
}
POST /2fa/disable
Headers:
Authorization: Bearer ACCESS_TOKEN
Body:
{
"totp_code": "123456"
}
// or { "backup_code": "1a2b-3c4d" }
setup-totp returns 400 if 2FA is already enabled. qr_code_png is only present when the server can render a PNG; otherwise qr_code_url holds the otpauth:// URI. /2fa/verify-totp is an alias of /2fa/verify-and-enable, and code is accepted in place of totp_code on every 2FA endpoint. Enabling returns 8 single-use backup codes (format xxxx-xxxx); they are shown only in this response, so store them safely. Only TOTP is supported ("method": "totp", the default).
2FA status and backup codes
GET /2fa/status
Headers:
Authorization: Bearer ACCESS_TOKEN
Response:
{
"enabled": true,
"method": "totp"
}
POST /2fa/recovery-codes // alias: POST /2fa/backup-codes
Headers:
Authorization: Bearer ACCESS_TOKEN
Body:
{
"totp_code": "123456"
}
Response:
{
"backup_codes": ["..."],
"recovery_codes": ["..."]
}
Generating new codes replaces the old ones and requires a current authenticator code (not a backup code).
Signing in when 2FA is enabled
For a user with 2FA enabled, POST /login does not return tokens. It returns a short-lived challenge instead:
{
"requires_2fa": true,
"method": "totp",
"email": "user@example.com",
"pending_token": "eyJ...",
"temp_token": "eyJ...",
"message": "Two-factor authentication required"
}
Complete the sign-in with the authenticator code (or one backup code). No Authorization header is needed; the pending token identifies the user.
POST /2fa/verify-login
Body:
{
"pending_token": "eyJ...",
"totp_code": "123456"
}
// or "backup_code": "1a2b-3c4d" instead of "totp_code"
Response:
{
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"token_type": "bearer",
"expires_in": 86400,
"user": { "id": "user-id", "email": "user@example.com", "email_verified": true }
}
The pending token expires after 10 minutes (temp_token is accepted as an alias). A used backup code cannot be reused. Wrong codes return 400 "Invalid verification code"; an expired or invalid pending token returns 401. Verification endpoints allow 10 attempts per minute per client IP and return 429 after that.
expires_in follows the project's JWT expiry setting (default 24 hours = 86400 seconds). As with every endpoint on this page, also send your anon key in the apikey header.
Attack Protection: CAPTCHA (Cloudflare Turnstile)
You can require a CAPTCHA on your project's end-user auth endpoints to block bots and credential stuffing. CAPTCHA is off by default; while it is off, existing calls are unchanged.
1. Create your own Turnstile widget
WoWSQL does not provide a shared CAPTCHA widget. In the Cloudflare dashboard, create a Turnstile widget for the hostname(s) where your login page runs, then copy its site key (public) and secret key (private).
2. Enable it for the project
Go to Project → Authentication → Attack Protection, turn on CAPTCHA (provider: Turnstile), paste the Site key and Secret key, and save. Both keys are required to save with CAPTCHA on. The secret is stored encrypted and is never shown again; paste a new one to rotate it.
3. Read the site key and render the widget
GET https://your-project-slug.wowsqlconnect.com/auth/v1/settings
apikey: YOUR_ANON_KEY
Response (excerpt):
{
"captcha": { "enabled": true, "provider": "turnstile", "site_key": "YOUR_SITE_KEY" }
}
4. Send the token with auth requests
When CAPTCHA is enabled, include the Turnstile token as captcha_token in the JSON body of these requests (or send it in a cf-turnstile-response or X-Captcha-Token header):
| Request | Endpoint |
|---|---|
| Sign up | POST /signup |
| Login | POST /login |
| Forgot password | POST /forgot-password |
| Send OTP | POST /otp/send |
| Send magic link | POST /magic-link/send |
| Resend verification email | POST /resend-verification |
POST /login
Headers:
Content-Type: application/json
Body:
{
"email": "user@example.com",
"password": "securepassword123",
"captcha_token": "TURNSTILE_TOKEN"
}
SDKs (3.9.2 and later): pass captchaToken (TypeScript, Dart, C#, Java, Kotlin, Swift) or captcha_token (Python, PHP, Ruby); Go uses WithCaptchaToken(...) / a trailing token argument and Rust uses the *_with_captcha methods. See each Client SDK page.
Errors
| Status | Message | Meaning |
|---|---|---|
400 | Security check failed. Please try again. | CAPTCHA is on and the token is missing or invalid. |
503 | CAPTCHA is enabled but this project has no Turnstile secret. Add your Cloudflare site key and secret in Attack Protection. | CAPTCHA is on but no secret key is saved. |