Refocus API for mobile apps
AI / automated clients — fetch the catalog (do not paste docs):
-
GET https://dashboard.refocus.co.in/api/docs/mobile— full JSON (CORS open) -
GET https://dashboard.refocus.co.in/api/docs/mobile?format=md— markdown -
https://refocus.co.in/developers/mobile-api.json— same JSON (static)
The JSON includes every mobile-relevant route, body fields, enums, status codes, error strings, cookies, Ably channels, and call-window constants. Prefer it over this HTML page when generating a client.
Build a React Native (or other native) client against the Refocus product
API. Canonical source:
docs/mobile-api.json on the product (test-dash)
branch —
GitHub.
No Bearer tokens for end users. Auth is NextAuth JWT in httpOnly cookies — use a cookie jar.
Overview
- Base URL:
https://dashboard.refocus.co.in(never the marketing apex for/api/*) - JSON:
application/json - NextAuth login/signout:
application/x-www-form-urlencoded
Minimum path
- Register → verify email → login (cookies)
GET /api/users/me→ requireemailVerified- List / create / join sessions
- Call window → Daily token → Daily RN SDK
- Ably token → friend chat
- Sign out
There is no in-session text-chat API beyond Daily A/V. In-call extras are tasks + cheer alerts over Ably.
Authentication
Cookies (production)
-
__Secure-next-auth.session-token— session JWT (Domain=.refocus.co.in) -
__Host-next-auth.csrf-token— CSRF (host-only on dashboard)
Persist Set-Cookie. Do not forge Origin/Referer
(403 cross-origin). No CORS — native HTTP only.
Register
POST /api/auth/register —
email, password required →
{ "id": "<userId>" }. Does not set a session.
Login (exact)
GET /api/auth/csrf→{ "csrfToken": "…" }-
POST /api/auth/callback/credentialsasx-www-form-urlencodedwithcsrfToken,callbackUrl,json=true, andemail+passwordorfirebaseIdToken
Success: { "url": "<callbackUrl>" } + session Set-Cookie. Failure
often 401 with error=CredentialsSignin in the url.
Without json=true you get a 302 — avoid that in RN.
Probe: GET /api/auth/session. Sign out:
POST /api/auth/signout (same form style + json=true).
Email verification
GET /api/auth/verify-email?token=… redirects (not JSON). Handle
via deep link / in-app browser, then re-check
GET /api/users/me. Resend:
POST /api/auth/resend-verification.
Booking & access gates
403 email:
{
"error": "Verify your email to use this feature. You can browse until then.",
"code": "EMAIL_NOT_VERIFIED"
} 403 first session (zero attendance → only one upcoming booking/request):
{
"error": "Attend your first session before booking another. Finish the one you already have, then you can schedule more.",
"code": "FIRST_SESSION_REQUIRED"
}
Call window: join allowed 10 minutes before start through
10 minutes after end (WRAP_UP token padding: 5
min).
Current user
GET /api/users/me— profile +emailVerified+ attendancePATCH /api/users/me— profile fields (verified)GET /api/users/username?q=— availabilityGET/PATCH /api/users/preferences-
POST /api/users/me/avatar— multipart fieldavatar(≤5 MB)
Sessions
Durations 25 | 50 | 75. Types
focus | deep-work | learning. Starts
on 30-minute marks. Horizon 90 days.
-
GET /api/sessions?from=&to=or?mineUpcoming=1— list includesdurationMin,sessionType,status, participants, occupied chips -
POST /api/sessions—{ "start", "durationMin", "sessionType", "quietOwner?" }→{ "id" } -
GET /api/sessions/[id]— sparse:{ "id", "owner_id", "start", "end", "participants": [{ "user_id", "joined_at", "quiet?" }], "youQuiet", "partner": { "userId", "name", "username", "avatarUrl" } } -
POST …/join—{ "quiet?" }→{ "ok": true }(400 if started/ended; 409 if full/overlap) POST …/leave— non-owner; optional messageDELETE …/[id]— owner cancel; optional messagePATCH …/[id]—name?,color?
Daily video
POST /api/sessions/[id]/daily/token inside the call window:
{
"token": "<daily-meeting-token>",
"roomName": "…",
"domain": "….daily.co"
}
Use the Daily React Native SDK with that token and domain. Also:
/tasks, /alert, /attendance.
Friends & session requests
-
GET /api/friends—{ friends, nextCursor, total } -
POST /api/friends/requests—{ "to_user_id" } -
GET /api/friends/requests?type=incoming|outgoing -
POST /api/friends/requests/[id]—{ "action": "accept" | "decline" } -
POST /api/session-requests—{ "to_user_id", "start", "durationMin", "message?" } -
GET /api/session-requests?type=&status= -
POST /api/session-requests/[id]—{ "action": "accept" | "decline", "message?" }→{ "ok": true, "sessionId": "<id>|null" } DELETE /api/session-requests/[id]— cancel pending
Chat & Ably
Friend REST: GET/POST /api/chat/[friendId] —
{ "type": "text", "content" } or { "type": "session-request", "start", "durationMin", "message?" }. Also unread-counts
and read markers.
Global: GET/POST /api/global-chat —
{ "content" }.
GET /api/ably/token → Ably TokenRequest (send cookies). Channels:
- DM:
chat:{sortedUserA}:{sortedUserB} - Inbox:
user:{userId}:chat - Global:
chat:global - Calendar:
sessions:updates - Tasks/alerts:
session:{sessionId}:tasks/session:{sessionId}:alerts
Community
GET /api/community/postsPOST /api/community/posts—{ "content" }- Like + comments under
/posts/[postId]/…
Public profile
GET /api/profile/[username] — no session for public profiles;
404 if private/missing.
Safety
POST /api/reports:
{
"targetType": "friend_message",
"targetId": "…",
"reason": "harassment",
"details?": "…",
"reportedUserId?"
}
Block: POST /api/users/blocks /
DELETE /api/users/blocks/[userId].
Errors
- 401 — no session
- 403 — origin, email, first-session, ban, call window
- 404 / 409 — not found / conflict
- 429 —
{ "error": "Too many requests", "retryAfter" }+Retry-After
Rough limits: auth 5/min · api 100/min · chat 30/min.
RN stack checklist
- Cookie-aware HTTP client targeting dashboard host only
- Daily React Native SDK for video
- Ably client for chat / session events
- Optional Firebase Auth if using Google →
firebaseIdToken - Deep links for email verification
Out of scope
- Admin / cron / ops endpoints
- Server-only secrets
- Marketing host JSON API
- Mobile Bearer auth (not implemented yet)