8.6 KiB
API Endpoints
Every backend endpoint the frontend calls. Paths are shown after the API base (today SARLINK_API_BASE_URL; in the target architecture the base becomes API_URL → nginx /api). Auth = requires Authorization: Token <token>.
Third-party integrations use different bases (PERSON_VERIFY_BASE_URL, OMADA_BASE_URL, hardcoded Invoice Ninja) — flagged inline.
Summary
| Method | Path | Purpose | Auth |
|---|---|---|---|
| Auth & onboarding | |||
| GET | /api/auth/users/filter/?mobile=&id_card= |
Does a permanent user exist / is verified | No |
| GET | /api/auth/users/temp/filter/?mobile=&id_card= |
Does a pending (temp) user exist | No |
| POST | /auth/mobile/ |
Send login OTP to a mobile | No |
| POST | /api/auth/register/ |
Register a new (temp) user | No |
| POST | /api/auth/register/verify/ |
Verify registration OTP | No |
| POST | /callback/auth/ |
Exchange OTP PIN → API token + user | No |
| POST | /auth/logout/ |
Invalidate token on sign-out | Yes |
| POST | /auth/login/ |
Username/password login — DEAD | No |
| Billing | |||
| POST | /api/billing/payment/ |
Create a device payment | Yes |
| GET | /api/billing/payment/?…&all_payments= |
List payments | Yes |
| GET | /api/billing/payment/{id} |
Get one payment | Yes |
| PATCH | /api/billing/payment/{id}/cancel/ |
Cancel a payment | Yes |
| PUT | /api/billing/payment/{id}/verify/ |
Verify/complete payment (TRANSFER/WALLET) | Yes |
| POST | /api/billing/topup/ |
Create a wallet top-up | Yes |
| GET | /api/billing/topup/?…&all_topups= |
List top-ups | Yes |
| GET | /api/billing/topup/{id} |
Get one top-up | Yes |
| PATCH | /api/billing/topup/{id}/cancel/ |
Cancel a top-up | Yes |
| PUT | /api/billing/topup/{id}/verify/ |
Verify a top-up payment | Yes |
| POST | /api/billing/admin-topup/ |
Admin credits a user's wallet | Yes |
| GET | /api/billing/wallet-transactions/?…&all_transactions= |
List wallet transactions | Yes |
| Devices | |||
| GET | /api/devices/?…&all_devices= |
List devices | Yes |
| GET | /api/devices/{id}/ |
Get one device | Yes |
| POST | /api/devices/ |
Register/add a device | Yes |
| PUT | /api/devices/{id}/block/ |
Block/unblock a device | Yes |
| Users / profile / geo | |||
| GET | /api/auth/atolls/ |
List atolls (+ nested islands) | No |
| GET | /api/auth/users/?… |
List users (admin) | Yes |
| GET | /api/auth/users/{id}/ |
Get a user profile by id | Yes |
| GET | /api/auth/profile/ |
Logged-in user's own profile | Yes |
| PUT | /api/auth/users/{id}/verify/ |
Admin verify a user | Yes |
| DELETE | /api/auth/users/{id}/reject/ |
Admin reject a user | Yes |
| PUT | /api/auth/users/{id}/update/ |
Update a user's details | Yes |
| PUT | /api/auth/users/{id}/agreement/ |
Upload/update agreement (multipart) | Yes |
| Third-party | |||
| GET | {PERSON_VERIFY}/api/person/{idCard} |
National identity lookup | No |
| — | Omada group/block endpoints | DEAD (moving to RADIUS) | X-API-key |
| POST | {ninja}/api/v1/clients |
Invoice Ninja client — DEAD | x-api-token |
Auth & onboarding
- GET
/api/auth/users/filter/—signin()(auth-actions) +checkIdOrPhone(). Checks a phone/ID exists & is verified before OTP; signup dupe-check. →{ ok, verified }. - GET
/api/auth/users/temp/filter/—checkTempIdOrPhone(). Pending-registration lookup. →{ ok, otp_verified, t_verified }. - POST
/auth/mobile/—signin(). Sends login OTP. Body{ mobile }. →{ detail }. - POST
/api/auth/register/—backendRegister()fromsignup(). Body{ firstname, lastname, username, address, id_card, dob, mobile, island, atoll, acc_no, terms_accepted, policy_accepted }. →{ t_username }. - POST
/api/auth/register/verify/—VerifyRegistrationOTP(). Body{ mobile, otp }. →{ message, verified }. - POST
/callback/auth/— the login token exchange (was NextAuthauthorize, nowverify-otp-form). Body{ token: pin }. →{ user, token, expiry }. 400/403/429 return error payloads (token[0]/message). - POST
/auth/logout/—logout(). Expects204. - POST
/auth/login/— DEAD (login()viaaxiosInstance, unused; login goes through/callback/auth/).
Billing
actions/payment.ts, queries/wallet.ts, actions/user-actions.ts.
- POST
/api/billing/payment/createPayment()— pay for cart devices. Body{ device_ids[], number_of_months }→Payment. - GET
/api/billing/payment/getPayments()— list;all_payments=truefor admin. →ApiResponse<Payment>. - GET
/api/billing/payment/{id}getPayment()→Payment. - PATCH
…/payment/{id}/cancel/cancelPayment()→Payment. - PUT
…/payment/{id}/verify/verifyPayment()/verifyDevicePayment()— Body{ method: "TRANSFER" | "WALLET" }. MIB verification is server-side; the frontend just sends the method. →Payment. - POST
/api/billing/topup/createTopup()— Body{ amount }→Topup. - GET
/api/billing/topup/getTopups()—all_topups=truefor admin. →ApiResponse<Topup>. - GET
/api/billing/topup/{id}getTopup()→Topup. - PATCH
…/topup/{id}/cancel/cancelTopup()→Topup. - PUT
…/topup/{id}/verify/verifyTopupPayment()→{ status, message, transaction? { ref, sourceBank, trxDate } }. - POST
/api/billing/admin-topup/adminUserTopup()— Body{ amount, user_id, description }. - GET
/api/billing/wallet-transactions/getWaleltTransactions()→ApiResponse<WalletTransaction>(transaction_type: "DEBIT" | "TOPUP").
Devices
queries/devices.ts (checkSession() for token).
- GET
/api/devices/getDevices()— paramsname, offset, limit, page, sortBy, status,all_devices=truefor admin. →ApiResponse<Device>. - GET
/api/devices/{id}/getDevice()→Device. - POST
/api/devices/addDeviceAction()— Body{ name, mac, registered: true }→Device. - PUT
/api/devices/{id}/block/blockDeviceAction()— Body{ blocked, reason_for_blocking, blocked_by: "ADMIN" | "PARENT" }. Parents forced toPARENT. →Device.
Users / profile / geo
queries/users.ts, queries/islands.ts, actions/user-actions.ts.
- GET
/api/auth/atolls/getAtolls()— atoll+island dropdowns on signup. →Atoll[](each with nestedislands). - GET
/api/auth/users/getUsers()— admin user list. →ApiResponse<UserProfile>. - GET
/api/auth/users/{id}/getProfileById()— profile & admin user pages. →UserProfile. - GET
/api/auth/profile/getProfile()— own profile (agreements, payment detail). →User. - PUT
/api/auth/users/{id}/verify/verifyUser()— →{ ok, mismatch_fields, … }; surfaces field mismatches. - DELETE
/api/auth/users/{id}/reject/rejectUser()— Body{ rejection_details };204→ revalidate/redirect. - PUT
/api/auth/users/{id}/update/updateUser()— Body = non-empty form fields. →Useror per-field errors. - PUT
/api/auth/users/{id}/agreement/updateUserAgreement()— multipart FormData (PDF). →{ agreement }.
Third-party
- GET
{PERSON_VERIFY_BASE_URL}/api/person/{idCard}getNationalPerson()(lib/person.ts) — LIVE. National identity lookup to cross-check user data during admin verification. ISRrevalidate: 60. →TNationalPerson { nic, name(_en), dob, gender, house_name(_en), island_name(_en), atoll(_en), constituency, … }. Memory note: planned to route through the backend instead of calling directly. - Omada (
actions/omada-actions.ts) — group profiles / add-to-group / block — DEAD, none imported by UI. Device blocking now uses backend/api/devices/{id}/block/. Consistent with the Omada→RADIUS migration. - Invoice Ninja (
actions/ninja/client.ts) — hardcoded staging URL, create client — DEAD.
Frontend's own API routes (app/api/) — not backend
app/api/auth/[...nextauth]/route.ts— NextAuth handler. To be removed in the static migration.app/api/check-devices/route.ts— stub returning{ message: "Request received" }; no backend call. Dead/placeholder.
Response envelope
List endpoints return ApiResponse<T> = { meta, links, data: T[] } (pagination). Errors surface as { message } / { detail } (see handleApiResponse in utils/tryCatch.ts, which is hardened against non-JSON error bodies).
Dead code to drop during the port
/auth/login/ (#8), /islands/, /inventory/, all Omada, Invoice Ninja, backendMobileLogin, app/api/check-devices, and the two axios helpers utils/axios-client.ts / utils/axiosInstance.ts (only used by dead calls).