API Reference
Drop Backend API Reference
Project:DropVersion:0.1.0Date:2026-02-23Author:Platform Architect (AI)Status:In ReviewReviewers:Alem Bašić (CEO)
Document History
are relative to
src/drop-app/src/.
Overview
Drop uses Next.js App Router API routes (app/api/). TheAll applicationresponses usesuse a PSD2consistent pass-throughJSON model — Drop never holds customer money. All funds remain in users' bank accounts; Drop uses AISP to read balances and PISP to initiate payments.envelope:
Base URL
| |
| |
|
Response Envelope
// Success
{ "data": { ... } } // Success
(list)
{ "data": [...], "pagination": { "page": 1, "limit": 20, "total": 100 } }
// Error
{ "error": "error_code"code", "message": "Human-readable message"...", "details": [...] } // Error
Authentication
Authentication is via httpOnly cookie (drop_token) containing a signed JWT (HS256, 24h expiry).
Pass-Through OIDCModel: Drop uses a PSD2 pass-through model — it NEVER holds customer money. There is theno solewallet, loginno method.
Mobileno clientstop-up. useUser Authorization:funds Bearer <token> (7d expiry, storedremain in AsyncStorage).their bank account at all times. Drop uses:
- AISP (Account Information Service Provider) — reads bank balance via Open Banking
- PISP (Payment Initiation Service Provider) — initiates transfers directly from user's bank account
The bank_accounts.balance field stores the last AISP-read balance from the user's real bank (cached for display) — NOT a Drop-held balance.
Authentication
RatePOST Limits/api/auth/register
Create a new user account.
app/api/auth/register/route.ts |
|
Authentication Endpoints
GET /api/auth/bankid
Initiate BankID OIDC login flow.
| Auth | None |
| Rate Limit |
Sets bankid_state httpOnly cookie. Returns { "redirectUrl": "https://bankid.no/authorize?..." }.
GET /api/auth/bankid/callback
BankID OIDC callback — creates/finds user, issues session cookie.
QueryRequest params:Body:
| Field | Type | Required | Validation |
|---|---|---|---|
| string | Yes | RFC-like regex, unique | |
| password | string | Yes | Min 8 chars, must contain letters + digits |
| firstName | string | Yes | validateName() — 1-100 chars, at least one letter, no HTML/script |
| lastName | string | Yes | Same as firstName |
| phone | string | No | International format
|
| dateOfBirth | string | Yes | ISO |
Success Response (201):
{
"data": {
"id": "usr_...",
"email": "[email protected]",
"firstName": "...",
"lastName": "...",
"dateOfBirth": "...",
"kycStatus": "pending",
"createdAt": "2026-..."
}
}
Error Responses:
| Status | Code | Condition |
|---|---|---|
| 400 | bad_request | Invalid JSON body |
| 409 | conflict | Email already registered |
| 422 | validation_error | Field validation failures (returned in details array) |
| 429 | rate_limited | Too many requests |
POST /api/auth/login
Authenticate with email and password.
| Field | Source |
|---|---|
| File | app/api/auth/login/route.ts |
| Auth | None |
| Rate Limit | 10 req/min per IP |
Request Body:
| Field | Type | Required |
|---|---|---|
| string | Yes | |
| password | string | Yes |
Success Response (200):
{
"data": {
"id": "usr_...",
"email": "...",
"firstName": "...",
"lastName": "...",
"kycStatus": "approved"
}
}
Error Responses:
| Status | Code | Condition |
|---|---|---|
| 400 | bad_request | Missing email or password |
| 401 | unauthorized | Invalid credentials |
| 429 | rate_limited | Too many requests |
GET /api/auth/me
Get current authenticated user with linked bank accounts.
| File | app/api/auth/me/route.ts |
| Auth | Required (cookie) |
Success Response (200):
{
"data": {
"id": "usr_a1b2c3"usr_...",
"email": "[email protected]"...",
"firstName": "Amir"...",
"lastName": "Bašić"...",
"totalBalance": 58030.0,
"bankAccounts": [
{
"id": "ba_1",
"bankName": "DNB",
"accountNumber": "1234.56.78901",
"balance": 45230.0,
"currency": "NOK",
"isPrimary": true
}
],
"kycStatus": "approved",
"createdAt": "2026-01-01T00:00:00.000Z"..."
}
}
Note: balance values are AISP-read from user's real bank — NOT Drop-held funds.
POST /api/auth/logout
Logout —and revoke all sessions.
| File | app/api/auth/logout/route.ts |
| Auth | Required (cookie) |
Calls revokeAllSessions() to invalidate all session records, then clears the auth cookie.
Success Response (200):
{ "message": "Logged out" }
POST /api/auth/refresh
Refresh the authentication token (issue new JWT, create new session record).
| Field | Source |
|---|---|
| File | app/api/auth/refresh/route.ts |
| Auth | Required (cookie) |
Success Response (200): { "message": "Logged out" }
POST /api/auth/refresh
Refresh JWT token.
Response (200):
{ "data": { "userId": "usr_...", "email": "...", "role": "user" } }
Deprecated Endpoints (410 Gone)
| |
| |
|
Transaction EndpointsTransactions
GET /api/transactions
List useruser's transactions with pagination and filtering.
| File | app/api/transactions/route.ts |
| Auth | Required |
Query Parameters:
| Param | Type | Default | Notes |
|---|---|---|---|
page |
int | 1 | Min 1 |
limit |
int | 20 | Min 1, Max 50 |
type |
string | remittance or qr_payment |
|
status |
string | processing, completed, or failed |
Success Response (200):
{
"data": [
{
"id": "tx_rem_1",
"type": "remittance",
"status": "completed",
"amount": -2000,
"currency": "NOK",
"recipientName": "Mama Jasmina",
"createdAt": "..."
}
],
"pagination": { "page": 1, "limit": 20, "total": 3 }
}
Note: amount is negated in the response (always shown as outgoing).
GET /api/transactions/[id]
Get single transaction details.details with exchange rate info.
| File | app/api/transactions/[id]/route.ts |
| Auth | Required |
Success Response (200):
{
"data": {
"id": "tx_rem_1",
"type": "remittance",
"status": "completed",
"sendAmount": 2000,
"sendCurrency": "NOK",
"receiveAmount": 23400,
"receiveCurrency": "RSD",
"exchangeRate": 11.7,
"fee": 10,
"total": 2010,
"recipientName": "Mama Jasmina",
"recipientCountry": "Serbia",
"createdAt": "...",
"completedAt": "..."
}
}
GET /api/transactions/summary
Get transaction summary statistics (all-time +and this-monththis statistics.month).
| File | app/api/transactions/summary/route.ts |
| Auth | Required |
Success Response (200):
{
"data": {
"allTime": {
totalCount,"totalCount": totalSent,3,
totalPaid,"totalSent": remittanceCount,5000,
qrPaymentCount"totalPaid": 129,
"remittanceCount": 2,
"qrPaymentCount": 1
},
"thisMonth": { "..." }
}
}
POST /api/transactions/remittance
Create a remittance (international money transfer.transfer).
| File | app/api/transactions/remittance/route.ts |
| Auth | Required |
| Rate Limit | |
| KYC | approved |
Request Body:
| Field | Type | Required | Validation |
|---|---|---|---|
recipientId |
string | Yes | Must belong to |
amount |
number | Yes | |
currency |
string | No | Defaults to NOK |
bankAccountId |
string | No | Defaults to primary bank account |
Business logic:Logic:
- Verify recipient belongs to user
- Look up exchange rate for recipient's currency
- Verify bank account exists and has sufficient balance
- Fee: 0.5% of
amount.amount - Debit bank account
+(atomiccreatetransaction) - Create transaction
(status:record with statusprocessing).
Success Response (201):
{
transaction"data": object{
with"id": exchange"tx_rem_...",
rate,"type": fee,"remittance",
ETA."status": "processing",
"sendAmount": 2000,
"sendCurrency": "NOK",
"receiveAmount": 23400,
"receiveCurrency": "RSD",
"exchangeRate": 11.7,
"fee": 10,
"feePercent": 0.5,
"total": 2010,
"recipientName": "...",
"recipientCountry": "Serbia",
"fromAccount": "DNB",
"eta": "1-2 business days",
"createdAt": "..."
}
}
Errors:Error Responses:
| Status | Code | Condition |
|---|---|---|
| 400 | bad_request |
Missing/invalid fields |
| 400 | no_bank_account |
No linked bank account |
| 402 | insufficient_balance |
|
| 403 | kyc_required |
KYC not approved |
| 404 | not_found |
Recipient not found |
| 422 | validation_error |
Unsupported currency corridor |
POST /api/transactions/qr-payment
Create a QR payment to a merchant.
| File | app/api/transactions/qr-payment/route.ts |
| Auth | Required |
| Rate Limit |
Request Body:
| Field | Type | Required | Validation |
|---|---|---|---|
merchantId |
string | Yes | Must exist |
amount |
number | Yes |
Business logic:Logic:
- Verify merchant exists
- Get user's primary bank account
- Fee: 1% of
amount.amount - Debit bank account (
status:atomic transaction) - Create transaction with status
completed(instant)
Success Response (201):
{
"data": {
"id": "tx_qr_...",
"type": "qr_payment",
"status": "completed",
"amount": 129,
"currency": "NOK",
"fee": 1.29,
"feePercent": 1,
"merchantName": "Ahmetov Kebab",
"merchantId": "mer_1",
"fromAccount": "DNB",
"createdAt": "..."
}
}
Recipients
GET /api/recipients
List user's recipients with pagination.
| Field | Source |
|---|---|
| File | app/api/recipients/route.ts |
| Auth | Required |
Query Parameters: page (default 1), limit (default 20, max 50)
Bank account numbers are masked in response (e.g., *****5678).
Supported Countries: RS (Serbia), BA (Bosnia), PL (Poland), PK (Pakistan), TR (Turkey)
POST /api/transactions/disclosurerecipients
GetAdd feea +new exchangerecipient.
| Field | Source |
|---|---|
| File | app/api/recipients/route.ts |
| Auth | Required |
Request Body:
| Field | Type | Required | Validation |
|---|---|---|---|
| name | string | Yes | validateName() |
| country | string | Yes | Must be in supported list |
| currency | string | Yes | - |
| bankAccount | string | Yes | - |
| bankName | string | No | Sanitized to 200 chars |
DELETE /api/recipients/[id]
Delete a recipient.
| Field | Source |
|---|---|
| File | app/api/recipients/[id]/route.ts |
| Auth | Required |
Returns 204 No Content on success. Returns 404 if recipient not found or not owned by user.
Cards (FUTURE — feature-flagged, all flags default to false)
Note: The entire Cards section is a FUTURE feature, gated behind feature flags. All card-related feature flags default to
false. These endpoints exist in code but return 404 when flags are disabled. Cards require a card issuing partner (e.g., Stripe Issuing) beforepaymentactivation.
GET /api/cards
List user's cards (Finansavtalelovenexcludes compliance)cancelled).
| File | app/api/cards/route.ts |
| Auth | Required |
POST /api/cards
Create a new card (virtual or physical).
| Field | Source |
|---|---|
| File | app/api/cards/route.ts |
| Auth | Required |
Request Body:
| Field | Type | Required | Notes |
|---|---|---|---|
| type | string | No | virtual (default) or physical |
GET /api/cards/[id]
Get card details. Card number is masked (---- ---- ---- XXXX), CVV is hidden (---).
| Field | Source |
|---|---|
| File | app/api/cards/[id]/route.ts |
| Auth | Required |
PCI-DSS compliant: never exposes full card number or CVV.
PATCH /api/cards/[id]
Freeze or unfreeze a card.
| Field | Source |
|---|---|
| File | app/api/cards/[id]/route.ts |
| Auth | Required |
Request Body: { type,"status": amount,"active" currency?,| recipientId?"frozen" }
Response (200):
{
"amount": 2000, "fee": 10, "feePercentage": 0.5,
"exchangeRate": 10.17, "receiveAmount": 20340, "receiveCurrency": "RSD",
"estimatedDelivery": "1-2 business days", "totalCost": 2010
}
GETDELETE /api/transactions/cards/[id]/receipt
GetCancel transactiona receipt.
Returns full receipt with amounts, fees, exchange rate, recipient info. 404 if not owned by user.
Recipient Endpoints
GET /api/recipients
List saved recipients. Bank account numbers maskedcard (soft delete — sets status to ).*****5678cancelled
app/api/cards/[id]/route.ts |
Query Params: page, limit (max 50). Supported countries: RS, BA, PL, PK, TR.
POST /api/recipients
Add a recipient.
Request Body: { name, country, currency, bankAccount, bankName? }
DELETE /api/recipients/[id]
Delete a recipient. Response (204). 404 if not found/owned.
| Auth | Required |
POST /api/cards/[id]/physical
Order physical version of a virtual card.
| Field | Source |
|---|---|
| File | app/api/cards/[id]/physical/route.ts |
| Auth | Required |
| Feature Flag | physicalCards (returns 404 if disabled) |
Request Body: { "address": "..." } (min 10 chars)
POST /api/cards/[id]/pin
Set PIN for a card.
| Field | Source |
|---|---|
| File | app/api/cards/[id]/pin/route.ts |
| Auth | Required |
| Feature Flag | cardPin (returns 404 if disabled) |
Request Body: { "pin": "1234" } (exactly 4 digits)
PIN is hashed with bcrypt before storage.
GET /api/cards/[id]/limits
Get spending limits for a card.
| Field | Source |
|---|---|
| File | app/api/cards/[id]/limits/route.ts |
| Auth | Required |
| Feature Flag | spendingLimits (returns 404 if disabled) |
PUT /api/cards/[id]/limits
Set a spending limit for a card.
| Field | Source |
|---|---|
| File | app/api/cards/[id]/limits/route.ts |
| Auth | Required |
| Feature Flag | spendingLimits (returns 404 if disabled) |
Request Body:
| Field | Type | Required | Validation |
|---|---|---|---|
| limitType | string | Yes | daily, weekly, monthly, or transaction |
| amount | number | Yes | Must be positive |
Replaces any existing limit of the same type.
Exchange Rate EndpointsRates
GET /api/rates
Get all NOK exchange rates (public).from NOK.
| File | app/api/rates/route.ts |
| Auth | None |
| Rate Limit |
Success Response (200):
{
"data": {
"baseCurrency": "NOK",
"rates": { "RSD": 11.7, "BAM": 1.04, "PLN": 0.41, "PKR": 26.8, "TRY": 3.45, "EUR": 0.089 },
"updatedAt": "..."
}
}
GET /api/rates/[currency]
Get rate for a specific currency from NOK. Includes fee: 0.005 (0.5% remittance fee).pair.
| File | app/api/rates/[currency]/route.ts |
| Auth | None |
| Rate Limit |
Response includes fee: 0.005 (0.5% remittance fee).
Merchant EndpointsNotifications
POSTGET /api/merchants/registernotifications
RegisterList asall merchantnotifications (upgradesfor role to merchant).
Request Body:user.
| Field | |||
|---|---|---|---|
| |
||
| |||
| |||
|
Returns QR code URI: drop://pay/{merchantId}
GET /api/merchants/dashboard
Merchant revenue stats.
Query Params: period = today (default) / week / month
Returns: { revenue, transactionCount, fees, netRevenue, nextPayout, payoutTime }
GET /api/merchants/qr
Get merchant QR code data.
Returns: { merchantId, businessName, qrValue: "drop://pay/{id}", address }
GET /api/merchants/transactions
List merchant's QR payment transactions. Customer names partially anonymized.
Notification Endpoints
GET /api/notifications
| Auth | Required |
| Feature Flag | notifications (default: enabled) |
PATCH /api/notifications
Mark notifications as read. Max 100 IDs per request.
| File | app/api/notifications/route.ts |
| Auth | Required |
| Feature Flag | notifications |
Request Body: { "notificationIds": ["noti_..."] }
- Max 100 IDs per request
- IDs validated against format
^[a-z]+_[a-f0-9]{16}$
Settings Endpoints
GET /api/settings
Get user settings (auto-creates defaults:defaults currency=NOK,if language=nb)none exist).
| File | app/api/settings/route.ts |
| Auth | Required |
Defaults: currency=NOK, language=nb, pushEnabled=true, emailEnabled=true
PATCH /api/settings
Update user settings.
| File | app/api/settings/route.ts |
| Auth | Required |
Request Body (all optional): { currency?, language?, pushEnabled?, emailEnabled? }
Currency
| Field | Type | Validation |
|---|---|---|
| currency | string | Whitelist: EUR, USD, GBP, BAM, CHF, PLN, NOK, RSD, TRY, PKR |
| language | string | Whitelist: nb, en, bs, sq |
| pushEnabled | boolean | - |
| emailEnabled | boolean | - |
GDPR & Compliance EndpointsMerchants
GETPOST /api/user/data-exportmerchants/register
ExportRegister allas usera data (GDPR Art. 20 — right to portability).merchant.
app/api/merchants/register/route.ts |
Returns full export: user profile, transactions, recipients, bank accounts, settings, consents.
DELETE /api/user/account
Request account deletion (GDPR Art. 17 — right to erasure). Data retained 5 years per hvitvaskingsloven.
Response (200): { "message": "Account scheduled for deletion", "retentionNote": "Data retained for 5 years per AML requirements" }
GET /api/consents
List GDPR consents.
POST /api/consents
Grant or withdraw consent.
| Auth | Required |
Request Body:
| Field | Type | Required | Validation |
|---|---|---|---|
businessName |
string | Yes | |
orgNumber |
Yes |
Exactly 9 digits, unique | |
| address | string | No | Sanitized to chars |
| bankAccount | string | Yes | Payout account |
RecordsUpgrades IPuser addressrole withto consentmerchant. action.Returns a QR code URI (drop://pay/{merchantId}).
GET /api/complaintsmerchants/dashboard
ListGet user'smerchant complaints.dashboard stats.
| File | app/api/merchants/dashboard/route.ts |
| Auth | Required (merchant role) |
Query Parameters: period — today (default), week, month
Returns: revenue, transactionCount, fees, netRevenue, nextPayout, payoutTime.
GET /api/merchants/qr
Get merchant QR code data.
| Field | Source |
|---|---|
| File | app/api/merchants/qr/route.ts |
| Auth | Required (merchant role) |
Returns: merchantId, businessName, qrValue (drop://pay/{id}), address.
GET /api/merchants/transactions
List merchant's QR payment transactions with pagination.
| Field | Source |
|---|---|
| File | app/api/merchants/transactions/route.ts |
| Auth | Required (merchant role) |
Query Parameters: page, limit
Customer names are partially anonymized (first name + last initial).
GDPR & Compliance
GET /api/user/data-export
Export all user data (GDPR right to data portability).
| Field | Source |
|---|---|
| File | app/api/user/data-export/route.ts |
| Auth | Required |
Creates a data_access_request record with type export and status completed.
Success Response (200):
{
"data": {
"user": {
"id": "usr_...",
"email": "...",
"first_name": "...",
"last_name": "...",
"phone": "+47...",
"date_of_birth": "1995-03-15",
"kyc_status": "approved",
"role": "user",
"created_at": "..."
},
"transactions": [ {...}, {...} ],
"recipients": [ {...}, {...} ],
"bankAccounts": [ {...} ],
"settings": { "currency": "NOK", "language": "nb", ... },
"consents": [ {...}, {...} ]
},
"exportedAt": "2026-02-17T..."
}
DELETE /api/user/account
Request account deletion (GDPR right to erasure).
| Field | Source |
|---|---|
| File | app/api/user/account/route.ts |
| Auth | Required |
QueryBehavior:
- Soft-deletes user (sets
deleted_attimestamp) - Revokes all active sessions
- Creates
data_access_requestwith typeerasureand statuscompleted - Important: Data retained for 5 years per AML/KYC legal requirements (hvitvaskingsloven)
Success Response (200):
{ "message": "Account scheduled for deletion",pagelimit"retentionNote": "Data retained for 5 years per AML requirements" }(max 100)
POSTGET /api/complaintsconsents
SubmitList auser's complaintGDPR (Finansavtaleloven §3-53 — 15 business day response SLA).consents.
| File | app/api/consents/route.ts |
| Auth | Required |
Success Response (200):
{
"data": [
{
"id": "con_...",
"user_id": "usr_...",
"consent_type": "terms",
"granted": 1,
"granted_at": "2026-02-17T...",
"withdrawn_at": null,
"ip_address": "192.0.2.1"
}
]
}
POST /api/consents
Grant or withdraw a consent.
| Field | Source |
|---|---|
| File | app/api/consents/route.ts |
| Auth | Required |
Request Body:
| Field | Type | Required | Validation |
|---|---|---|---|
consentType |
string | Yes | Must be one of: terms, privacy, marketing, cookies_analytics, cookies_marketing |
| granted | boolean | Yes | true to grant, false to withdraw |
Behavior:
- If consent exists: updates
grantedfield and sets eithergranted_atorwithdrawn_at - If consent doesn't exist: creates new consent record
- Records user's IP address with consent action
Success Response (200 for update, 201 for new):
{
"data": {
"id": "con_...",
"consent_type": "marketing",
"granted": 1,
"granted_at": "2026-02-17T...",
"withdrawn_at": null,
"ip_address": "192.0.2.1"
}
}
Error Responses:
| Status | Code | Condition |
|---|---|---|
| 400 | bad_request | Invalid consent type or missing fields |
GET /api/complaints
List user's complaints.
| Field | Source |
|---|---|
| File | app/api/complaints/route.ts |
| Auth | Required |
Query Parameters:
| Param | Type | Default | Notes |
|---|---|---|---|
| page | int | 1 | Pagination page number |
| limit | int | 10 | Items per page, max 100 |
Success Response (200):
{
"data": [
{
"id": "cmp_...",
"category": "transaction",
"subject": "Transaction delayed",
"description": "My remittance to Serbia is delayed...",
"status": "received",
"resolution": null,
"created_at": "2026-02-17T...",
"resolved_at": null
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 3,
"totalPages": 1
}
}
POST /api/complaints
Submit a complaint (Finansavtaleloven §3-53 compliance).
| Field | Source |
|---|---|
| File | app/api/complaints/route.ts |
| Auth | Required |
Request Body:
| Field | Type | Required | Validation |
|---|---|---|---|
| category | string | Yes | Must be one of: transaction, service, fees, privacy, technical, other |
subject |
string | Yes | Max 200 |
description |
string | Yes | Max 2000 |
Success Cards EndpointsResponse (FUTURE201):
{
Feature-Flagged,"data": All{
Disabled)"id": All"cmp_...",
card"category": endpoints"fees",
are"subject": behind"High featuretransfer flagsfee",
defaulting"description": "...",
"status": "received",
"created_at": "2026-02-17T..."
},
"commitmentNote": "We will review and respond to falseyour complaint within 15 business days per Finansavtaleloven §3-53"
}
.
Error card issuing partner before activation.Responses:
| Condition | ||
|---|---|---|
|
bad_request | Invalid category or empty fields |
POST /api/cardstransactions/disclosure
Get full transaction fee and exchange rate disclosure before initiating payment.
| Field | Source |
|---|---|
| File | |
Auth |
|
| |
| |
| |
| |
| |
| Required |
CardRequest numbersBody:
| Field | Type | Required | Notes |
|---|---|---|---|
| type | string | Yes | remittance or qr_payment |
| amount | number | Yes | Must be positive |
| currency | string | No | Defaults to NOK |
| recipientId | string | Conditional | Required for remittance |
Success Response (200):
----{----"amount":----2000,XXXX"fee": 10, "feePercentage": 0.5, "exchangeRate": 10.17, "receiveAmount": 20340, "receiveCurrency": "RSD", "estimatedDelivery": "1-2 business days", "totalCost": 2010 })
Fee Calculation:
- Remittance: 0.5% of amount
- QR payment: 1.0% of amount
Delivery Time:
- QR payment: "Instant"
- Remittance (EEA): "1-2 business days"
- Remittance (non-EEA): "2-4 business days"
GET /api/transactions/[id]/receipt
Get transaction receipt with full details.
| Field | Source |
|---|---|
| File | app/api/transactions/[id]/receipt/route.ts |
| Auth | Required |
Success Response (200):
{
"data": {
"transactionId": "tx_rem_1",
"date": "2026-02-17T...",
CVV"type": never"remittance",
exposed."amount": PCI-DSS2000,
compliant"currency": masking."NOK",
"fee": 10,
"exchangeRate": 10.17,
"receiveAmount": 20340,
"receiveCurrency": "RSD",
"recipient": {
"name": "Mama Jasmina",
"country": "RS"
},
"reference": "tx_rem_1",
"status": "completed",
"estimatedCompletion": null,
"completedAt": "2026-02-17T..."
}
}
Error Responses:
| Status | Code | Condition |
|---|---|---|
| 404 | not_found | Transaction not found or not owned by user |
Health Check
GET /api/health
System health —check (no auth required.required).
| Field | Source |
|---|---|
| File | app/api/health/route.ts |
| Auth | None |
Success Response (200):
{
"data": {
"status": "ok",
"version": "0.1.0",
"uptime": 3600,
"checks": {
"db": { "status": "pass"connected",
"latencyMs"dbLatencyMs": 2, "driver": "pg" },
"services": { "mode": "production" }
},1,
"timestamp": "2026-02-23T12:00:00.000Z"
}..."
}
ResponseReturns (503 — DB unreachable):with {status: "data":error"{if "status":database "down",is "checks": { "db": { "status": "fail" } } } }unreachable.