Skip to main content
Infidec Marketplace logo
v1.0.0

Type to search pages and sections, e.g. “razorpay”, “package name”, “SHA”.

Auth Endpoints

Register, login, OTP, password reset, profile, device registration, logout and account deletion. How the API and Firebase Authentication share the login.

The auth routes live in functions/src/routes/auth.ts, under /api/v1/auth. Sessions are Firebase Auth sessions: the API checks or creates the account and returns the e-mail to sign in with; the client signs in with the Firebase SDK and sends the ID token on every request.

The login flow

  1. Call the API

    POST /auth/login with login (e-mail or phone) and password, or POST /auth/register.

  2. Read auth_email

    The answer contains data.user and data.auth_email. For phone-only accounts this is the synthetic e-mail p<digits>@phone.classiadshub.app. data.token is always null.

  3. Sign in to Firebase

    signInWithEmailAndPassword(auth, auth_email, password).

  4. Call the API with the ID token

    Authorization: Bearer <await user.getIdToken()> on every request.

Google and Apple sign-in run entirely in the Firebase SDK (signInWithPopup on the website, provider sign-in in the app). Afterwards the client calls GET /auth/me: the API links the account to an existing user with the same e-mail or phone, or creates a new customer. POST /auth/social/{provider} only answers 410 with that hint.

Endpoints

MethodPathAuthBody / queryReturns
POST/auth/registerPublicname (required, max 150), email (email, max 191), phone (max 32), password (required, min 8), password_confirmation. Either email or phone is required201 { user, auth_email, token: null, otp }. Creates users/{id} (role customer) and the Auth user with uid = id, then sends an OTP to the e-mail or phone (purpose: register)
POST/auth/loginPubliclogin (required: e-mail or phone), password (required), device (optional){ user, auth_email, token: null }. Updates last_login_at. 422 These credentials do not match our records., 403 Your account is suspended.
POST/auth/otp/sendPublicidentifier (required), channel (sms · email), purpose (register · login · reset · verify){ otp_id, debug_code }
POST/auth/otp/verifyPublicidentifier, purpose, code (all required){ verified: true }. For register / verify it sets email_verified_at or phone_verified_at (and emailVerified in Firebase Auth). 422 Invalid or expired code.
POST/auth/password/forgotPubliclogin (required)Always If the account exists, a reset code has been sent. When it exists, data is the OTP block (purpose: reset)
POST/auth/password/resetPubliclogin, code, password (min 8), password_confirmationSets the new Firebase password and revokes refresh tokens: Password reset. Please log in again.
POST/auth/social/{provider}Public—410 Sign in with the Firebase Auth SDK for this provider, then call GET /auth/me.
GET/auth/meSigned in—The user with seller_profile, address and login_type. Provisions provider sign-ins on first call
PUT/auth/profileSigned inJSON or multipart: name, email, phone, address (max 500), preferred_language (max 8), preferred_currency (max 8), file avatar (image ≤ 5 MB)The updated user. E-mail and phone must stay unique. A new avatar replaces the old file in avatars/{id}/
POST/auth/logoutSigned in—Logged out. (the client signs out of Firebase)
POST/auth/devicesSigned infcm_token (required), platform (android · ios · web), device_name{ device_id }. Upserts user_devices/{id} for push
DELETE/auth/accountSigned inpassword (required for password accounts)Anonymises the profile (Deleted User, e-mail deleted_<id>@deleted.local, phone and address cleared, status: banned, deleted_at), deletes the avatar and the devices, deletes the Firebase Auth user. 422 Password is incorrect.

The user object

data.user
{
  "id": 12,
  "name": "Asha Mehta",
  "email": "asha@example.org",
  "phone": "+919000000001",
  "avatar_path": "https://firebasestorage.googleapis.com/v0/b/your-project-id.firebasestorage.app/o/avatars%2F12%2F…?alt=media",
  "status": "active",
  "is_verified": false,
  "email_verified": true,
  "phone_verified": false,
  "preferred_language": "en",
  "preferred_currency": "USD",
  "roles": ["customer", "seller"],
  "seller_profile": { "id": 12, "display_name": null, "bio": null, "business_name": null, "website": null, "rating_avg": 4.5, "rating_count": 2, "member_since": "2026-10-01T10:00:00.000Z" },
  "created_at": "2026-10-01T09:58:12.000Z"
}

Public views of other users (ad sellers, reviewers, followers) hide email and phone.

OTP codes

functions/src/lib/otp.ts creates a numeric code of Code length digits (4–8, default 6) that expires after Expiry (minutes) (default 10). Only the SHA-256 hash is stored in otp_verifications. Sending a new code for the same identifier and purpose closes the old one. A code allows 5 attempts.

Examples

Register
curl -X POST https://us-central1-your-project-id.cloudfunctions.net/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{"name":"Asha","email":"asha@example.org","password":"Secret123","password_confirmation":"Secret123"}'
Login from a web client
const r = await fetch(`${API}/auth/login`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ login, password }),
}).then((x) => x.json());
await signInWithEmailAndPassword(auth, r.data.auth_email, password);
const token = await auth.currentUser!.getIdToken();   // send as Authorization: Bearer <token>

Next: Catalogue & Content Endpoints →

Something unclear or out of date? Tell us. contact@infidec.com