Build and Push Docker Images / Build and Push Docker Images (push) Failing after 8s
120 lines
8.6 KiB
Markdown
120 lines
8.6 KiB
Markdown
# 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()` from `signup()`. 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 NextAuth `authorize`, now `verify-otp-form`). Body `{ token: pin }`. → `{ user, token, expiry }`. 400/403/429 return error payloads (`token[0]` / `message`).
|
|
- **POST `/auth/logout/`** — `logout()`. Expects `204`.
|
|
- **POST `/auth/login/`** — DEAD (`login()` via `axiosInstance`, 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=true` for 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=true` for 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()` — params `name, offset, limit, page, sortBy, status`, `all_devices=true` for 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 to `PARENT`. → `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 nested `islands`).
|
|
- **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. → `User` or 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. ISR `revalidate: 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).
|