Documentation Index
Fetch the complete documentation index at: https://docs.handauncle.com/llms.txt
Use this file to discover all available pages before exploring further.
The authentication service wraps Auth0 so the mobile and web clients never talk
to Auth0 directly. All routes live under /api/v1/auth unless otherwise noted.
| Flow | Endpoint(s) | Description |
|---|
| Email/password | POST /signup, POST /signin | Create or authenticate users with the native database connection |
| Google OAuth | POST /google, POST /login/google, GET /login/google, GET /callback/google | Exchange Google ID tokens or run the redirect-based flow |
| Tokens | POST /refresh, POST /signout | Rotate or revoke Auth0 tokens |
| Profile | GET /me, PATCH /me | Full profile overview with usage stats, update profile with avatar upload |
| Phone OTP | POST /send-otp, POST /resend-otp, POST /verify-otp | Exotel-backed OTP login |
| Webhooks | POST /webhooks/post-registration, POST /post-login | Auth0 server-to-server sync |
| Health | GET /health | Service heartbeat |
Prerequisites
- Auth0 tenant with the database connection enabled and client credentials set
in
.env (AUTH0_DOMAIN, AUTH0_CLIENT_ID, etc.).
- Front-channel URLs registered in Auth0 for
GET /login/google and
GET /callback/google.
- Exotel credentials for OTP routes and a verified sender ID.
- Bearer token (Auth0 access token) when hitting any protected route such as
/api/v1/auth/me. Use POST /signin or /google
to obtain one.
Email + password
curl -X POST https://api.handauncle.com/api/v1/auth/signup \
-H "Content-Type: application/json" \
-d '{
"email": "investor@example.com",
"password": "GrowWealth123",
"name": "Puneet"
}'
Requirements:
- Password must be ≥8 chars and include uppercase, lowercase, and a digit
(signupRequestSchema in src/services/auth/types/auth-schemas.ts).
- Successful signup/signin returns
{ accessToken, idToken, refreshToken, expiresIn, user }.
POST /signin takes the same body (email + password) and returns the same
envelope. Tokens are Auth0-issued JWTs referenced throughout the API.
Google OAuth
1. Token exchange (mobile/native)
curl -X POST https://api.handauncle.com/api/v1/auth/google \
-H "Content-Type: application/json" \
-d '{ "idToken": "<google-id-token>" }'
Mobile clients obtain the Google ID token via the platform SDK and exchange it
server-side. Try it via the POST /api/v1/auth/google panel.
2. Redirect flow (web)
GET /api/v1/auth/login/google → redirects to Auth0’s hosted login page
(optional state query param supported).
GET /api/v1/auth/callback/google → handles the authorization code, fetches
user info, syncs MongoDB via userSyncService, and forwards the tokens plus
the original state back to the frontend.
Both flows call authOrchestrationService.googleAuth() and return the standard
token envelope.
Token lifecycle
Refresh
POST /api/v1/auth/refresh with body { "refreshToken": "<token>" } returns
{ accessToken, idToken, expiresIn }. No Bearer token required—the refresh token
is validated via Auth0 (tokenService.refreshAccessToken).
Use the Refresh Access Token playground to verify your refresh
tokens are wired correctly.
Signout
POST /api/v1/auth/signout accepts an optional refreshToken. When provided,
the backend revokes it via Auth0; when omitted, the call simply returns
{ success: true, message: "Successfully signed out" } so clients can clear
local state.
Profile (GET & PATCH /me)
The /me endpoint is the unified profile endpoint that replaces the old /profile route.
Get Profile
GET /api/v1/auth/me requires Authorization: Bearer <Access Token>. Returns the
full profile overview including user data, usage statistics, and profile context:
{
"success": true,
"data": {
"user": {
"id": "683b7e9f465b1b4e6753627a4f",
"email": "investor@example.com",
"fullName": "Puneet",
"avatarUrl": "https://cdn.auth0.com/...",
"preferences": { "language": "en", "theme": "dark" }
},
"usage": {
"conversations": { "total": 42, "active": 38, "archived": 3, "deleted": 1, "lastActiveAt": "..." },
"shares": { "total": 5, "active": 4, "expired": 0, "revoked": 1, "totalViews": 127, "lastSharedAt": "..." }
},
"profileContext": {
"static": ["..."],
"recent": ["..."],
"frequent": ["..."]
}
}
}
If the user does not exist locally, the controller auto-creates it based on the
Auth0 payload before responding.
Update Profile
PATCH /api/v1/auth/me accepts partial updates for fullName or preferences
(language, theme, notifications), and supports avatar upload via multipart form data.
Returns the updated profile overview.
JSON Request (no avatar):
curl -X PATCH https://api.handauncle.com/api/v1/auth/me \
-H "Authorization: Bearer <access-token>" \
-H "Content-Type: application/json" \
-d '{ "fullName": "Puneet Sharma", "preferences": { "theme": "dark" } }'
Multipart Request (with avatar):
curl -X PATCH https://api.handauncle.com/api/v1/auth/me \
-H "Authorization: Bearer <access-token>" \
-F "avatar=@/path/to/photo.jpg" \
-F 'data={"fullName": "Puneet Sharma"}'
Delete Avatar:
curl -X PATCH https://api.handauncle.com/api/v1/auth/me \
-H "Authorization: Bearer <access-token>" \
-H "Content-Type: application/json" \
-d '{ "_clearAvatar": true }'
Supports JPEG, PNG, GIF, and WebP images. Large images are automatically compressed.
Phone OTP (Exotel)
Phone OTP authentication via Exotel SMS. All routes are under /api/v1/auth.
| Header | Required | Description |
|---|
x-device-id | Yes | Stable, unique per device/installation |
x-platform | No | ios, android, or web |
Send OTP
curl -X POST https://api.handauncle.com/api/v1/auth/send-otp \
-H "Content-Type: application/json" \
-H "x-device-id: device-uuid-123" \
-H "x-platform: android" \
-d '{ "phone": "+919876543210" }'
Kicks off an Exotel SMS and enforces cooldowns via otpOrchestrationService.sendOTP.
Resend OTP
curl -X POST https://api.handauncle.com/api/v1/auth/resend-otp \
-H "Content-Type: application/json" \
-H "x-device-id: device-uuid-123" \
-d '{ "phone": "+919876543210" }'
Respects OTP_RESEND_COOLDOWN_SECONDS (default 60s) before dispatching another SMS.
Verify OTP
curl -X POST https://api.handauncle.com/api/v1/auth/verify-otp \
-H "Content-Type: application/json" \
-H "x-device-id: device-uuid-123" \
-d '{
"phone": "+919876543210",
"otp": "123456"
}'
On success, returns the standard auth envelope with Auth0 tokens:
{
"success": true,
"data": {
"accessToken": "eyJhbGciOiJSUzI1NiIs...",
"idToken": "eyJhbGciOiJSUzI1NiIs...",
"refreshToken": "v1.MjAyNS0xMi0wMg...",
"expiresIn": 86400,
"user": {
"id": "auth0|692e9f465b1b4e6753627a4f",
"phone": "+919876543210",
"name": "HU Phone 3210",
"phoneVerified": true,
"email": "919876543210@sms.handauncle.app"
}
}
}
The accessToken can be used with all authenticated endpoints just like email/password tokens.
Webhooks (server-to-server)
| Endpoint | Auth | Purpose |
|---|
POST /api/v1/auth/webhooks/post-registration | Auth0 JWT + optional X-Webhook-Secret | Primary hook triggered by Auth0 Actions after signup to create the MongoDB user |
POST /api/v1/auth/post-login | Auth0 JWT | Legacy hook for syncing profile updates after login |
Both routes use auth0JwtMiddleware and are not intended for client apps.
Health
GET /api/v1/auth/health returns the provider info and the exported endpoints,
useful for monitoring or smoke tests.
All controllers extend BaseController and emit the shared error envelope:
{
"success": false,
"error": {
"message": "Validation error",
"code": "ValidationError"
},
"meta": {
"timestamp": "...",
"requestId": "..."
}
}