Skip to main content

Authentication API

Manage user authentication, password resets, wallet sign-in, Farcaster identity, and token gating.

Sign up

POST /api/register
Protected by bot detection. Automated or non-browser requests may be rejected.

Request body

FieldTypeRequiredDescription
emailstringYesUser email address
passwordstringYesPassword (minimum 8 characters)
namestringNoDisplay name (defaults to email if omitted)
referralCodestringNoAlphanumeric referral code that may include hyphens (max 20 characters). Case-insensitive. Both the new user and the referrer receive credit when a valid code is provided.

Response

{
  "id": "user_123",
  "email": "user@example.com",
  "name": "John Doe"
}

Errors

CodeDescription
400Email and password required, invalid email format, password too short, or invalid referral code
403Request blocked by bot detection
409User already exists
429Too many requests

Sign in

POST /api/auth/callback/credentials

Request body

{
  "email": "user@example.com",
  "password": "securepassword"
}

OAuth sign in

OAuth providers support automatic account linking. If a user with the same email address already exists, the OAuth account is linked to the existing user on first sign-in. This lets users who originally signed up with email and password add GitHub or Google login without creating a duplicate account.

GitHub

GET /api/auth/github
Redirects to GitHub OAuth flow. Requires GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET to be configured.

Google

GET /api/auth/google
Redirects to Google OAuth flow. Requires GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET to be configured.

Wallet sign in (SIWE)

POST /api/auth/callback/wallet
Sign in using an Ethereum wallet via Sign-In with Ethereum (SIWE). This flow is designed for Base smart wallets and supports ERC-6492 signature verification for pre-deployed wallets.

How it works

  1. The client opens the Base Account SDK popup and requests a SIWE signature on Base Mainnet (chain ID 0x2105).
  2. The signed SIWE message and signature are sent to the wallet NextAuth credentials provider.
  3. The server parses the SIWE message, validates the domain, and verifies the signature.
  4. If no account exists for the wallet address, a new user is created automatically.
  5. If an account with the same email already exists (from a previous OAuth or email sign-up), the wallet is linked to the existing account.

Request body

FieldTypeRequiredDescription
messagestringYesThe full SIWE message string
signaturestringYesThe wallet signature of the SIWE message (0x-prefixed)

Response

On success, a session cookie is set and the user is redirected to the callback URL. The response follows the standard NextAuth credentials callback flow.

Account linking

When a wallet signs in, the system checks for an existing user by the wallet-derived email address. If a matching user is found (for example, one who previously signed up with email and password or OAuth), the wallet provider is linked to that existing account. This prevents duplicate accounts and lets users access the same data regardless of which sign-in method they use.

Errors

CodeDescription
401Missing message or signature, SIWE domain mismatch, or signature verification failed
The SIWE domain is validated against the configured application URL to prevent replay attacks from other sites.

Get current user

GET /api/settings
Requires session authentication. Returns the current user profile.

Response

{
  "id": "user_123",
  "email": "user@example.com",
  "name": "John Doe",
  "plan": "solo",
  "credits": 0,
  "twoFactorEnabled": false
}

Errors

CodeDescription
401Unauthorized
404User not found

Update profile

You can update your profile using either POST or PATCH.
POST /api/settings

Request body (POST)

FieldTypeRequiredDescription
namestringNoNew display name
emailstringNoNew email address (must be unique)

Errors (POST)

CodeDescription
400Invalid email format
401Unauthorized
409Email address already in use
PATCH /api/settings

Request body (PATCH)

FieldTypeRequiredDescription
namestringNoNew display name
notificationsobjectNoNotification preferences

Change password

POST /api/settings/password

Request body

FieldTypeRequiredDescription
currentPasswordstringYesCurrent password
newPasswordstringYesNew password (minimum 8 characters)

Response

{
  "success": true
}

Errors

CodeDescription
400New password must be at least 8 characters
401Unauthorized or current password incorrect

Forgot password

POST /api/auth/forgot-password
Protected by bot detection. Rate-limited per IP address. Always returns the same response regardless of whether the email exists, to prevent user enumeration.

Request body

FieldTypeRequiredDescription
emailstringYesAccount email address

Response

{
  "message": "If an account exists, a reset link has been sent"
}

Errors

CodeDescription
400Email is required, invalid email format, or email service validation error
403Request blocked by bot detection
429Too many requests
500Internal server error

Reset password

POST /api/auth/reset-password
Rate-limited per IP address.

Request body

FieldTypeRequiredDescription
tokenstringYesReset token from the email link
passwordstringYesNew password (minimum 6 characters)

Response

{
  "message": "Password reset successfully"
}

Errors

CodeDescription
400Token and password are required, password too short (minimum 6 characters), or invalid/expired token
404User not found
429Too many requests

Farcaster authentication

Verify Farcaster identity

POST /api/auth/farcaster/verify
GET /api/auth/farcaster/verify
The GET method returns endpoint metadata. The POST method verifies a Farcaster ID token and optionally checks $RAVE token gating on Base.

Request body

FieldTypeRequiredDescription
fidTokenstringYesFarcaster ID token
addressstringNoEthereum address for token gating check

Response

{
  "success": true,
  "sessionToken": "base64-encoded-session",
  "address": "0x...",
  "message": "Farcaster verification successful",
  "tokenGated": true,
  "accessLevel": "premium"
}

Errors

CodeDescription
401Missing Farcaster ID token
403Token gating failed (insufficient $RAVE balance). Response includes required, minBalance fields
500Verification failed

Refresh Farcaster token

POST /api/auth/farcaster/refresh
GET /api/auth/farcaster/refresh
The GET method returns endpoint metadata.

Request body

FieldTypeRequiredDescription
refreshTokenstringYesBase64-encoded refresh token

Response

{
  "success": true,
  "sessionToken": "base64-new-session",
  "expiresIn": 86400,
  "message": "Token refreshed successfully"
}

Errors

CodeDescription
400Missing refresh token
401Invalid refresh token
500Token refresh failed

Token gating

Verify token access (POST)

POST /api/auth/token-gating/verify
Checks whether a wallet holds sufficient $RAVE tokens on Base mainnet.

Request body

FieldTypeRequiredDescription
fidstringYesFarcaster ID
addressstringYesEthereum address (0x-prefixed, 42 characters)

Response

{
  "fid": "12345",
  "address": "0x...",
  "hasAccess": true,
  "tokenGated": true,
  "minBalance": "1000000000000000000",
  "token": "RAVE",
  "chain": "base",
  "message": "User has sufficient $RAVE balance",
  "timestamp": "2026-03-19T00:00:00Z"
}

Errors

CodeDescription
400Missing fid or address, or invalid Ethereum address
500Verification failed

Verify token access (GET)

GET /api/auth/token-gating/verify?address=0x...

Query parameters

ParameterTypeRequiredDescription
addressstringYesEthereum address (0x-prefixed, 42 characters)

Response

{
  "address": "0x...",
  "hasAccess": true,
  "tokenGated": true,
  "minBalance": "1000000000000000000",
  "token": "RAVE",
  "chain": "base",
  "contractAddress": "0x6EE72eEDEfBa8937Ec8c36dEd9B8c1ef9ca7A3db",
  "rpcEndpoint": "https://mainnet.base.org"
}

Webhook events

EventDescription
user.createdNew user registered
user.updatedProfile updated
user.deletedAccount deleted