All API route handlers live under app/api/ following Next.js 14 App Router conventions.
app/api/
├── health/
│ └── route.ts # GET /api/health — public health check
├── auth/
│ ├── nonce/
│ │ └── route.ts # POST /api/auth/nonce
│ ├── login/
│ │ └── route.ts # POST /api/auth/login
│ └── logout/
│ └── route.ts # POST /api/auth/logout
├── user/
│ └── profile/
│ └── route.ts # GET /api/user/profile
├── split/
│ ├── route.ts # GET, POST /api/split
│ └── calculate/
│ └── route.ts # GET /api/split/calculate
├── goals/
│ └── route.ts # GET, POST /api/goals
├── bills/
│ └── route.ts # GET, POST /api/bills
├── insurance/
│ └── route.ts # GET, POST /api/insurance
├── family/
│ └── route.ts # GET, POST /api/family
├── send/
│ └── route.ts # POST /api/send
├── remittance/
│ └── route.ts # Remittance endpoints
├── anchor/
│ └── route.ts # Anchor platform integration
└── webhooks/
└── route.ts # Webhook handlers
app/api/[domain]/[action]/route.ts
- domain — the feature area (e.g.
split,goals,bills) - action — optional sub-action (e.g.
calculate,pay,cancel) - route.ts — exports named functions:
GET,POST,PUT,DELETE
# Health check (public)
curl http://localhost:3000/api/health
# Protected route (requires session cookie)
curl http://localhost:3000/api/split \
-H "Cookie: remitwise-session=<your-session-token>"- Create the folder:
app/api/[domain]/[action]/ - Create
route.tsinside it - Export the HTTP methods you need:
import { NextResponse } from "next/server";
export async function GET() {
return NextResponse.json({ data: "example" }, { status: 200 });
}
export async function POST(request: Request) {
const body = await request.json();
return NextResponse.json({ received: body }, { status: 201 });
}- If the route is protected, wrap with
withAuth(see Authentication section below).
All API routes use cookie-based session authentication. The session cookie is set after successful login and verified on protected routes.
The withAuth helper in /lib/auth.ts protects routes by:
- Checking for a valid session cookie
- Returning 401 if no session exists
- Passing the session to the route handler
Usage:
import { withAuth } from '@/lib/auth';
async function handler(request: NextRequest, session: string) {
// Your logic here - session is guaranteed to exist
return NextResponse.json({ data: 'protected' });
}
export const GET = withAuth(handler);| Method | Endpoint | Description |
|---|---|---|
| GET | /api/health |
Health check |
| POST | /api/auth/nonce |
Generate nonce for wallet signature |
| POST | /api/auth/login |
Login with signed nonce |
| POST | /api/auth/logout |
Clear session |
All protected routes return 401 Unauthorized if no valid session exists.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/user/profile |
Get user profile |
| GET | /api/split |
Get current split configuration |
| GET | /api/split/calculate?amount=100 |
Calculate split amounts for given amount |
| POST | /api/split |
Configure money split |
| GET | /api/goals |
List savings goals |
| POST | /api/goals |
Create savings goal |
| GET | /api/bills |
List bills |
| POST | /api/bills |
Create/pay bill |
| GET | /api/insurance |
List insurance policies |
| POST | /api/insurance |
Create insurance policy |
| GET | /api/family |
List family members |
| POST | /api/family |
Add family member |
| POST | /api/send |
Send money transaction |
{
"error": "Unauthorized"
}{
"error": "Internal server error"
}- Request Nonce:
POST /api/auth/noncewith{ publicKey } - Sign Nonce: User signs nonce with wallet
- Login:
POST /api/auth/loginwith{ publicKey, signature } - Session Cookie: Server sets httpOnly session cookie
- Protected Requests: Cookie automatically sent with requests
- Logout:
POST /api/auth/logoutclears session
- Session stored as httpOnly cookie for security
- Session value currently stores publicKey (TODO: use proper session ID)
- All protected routes use
withAuthwrapper - Signature verification not yet implemented (TODO)
- Session storage in database not yet implemented (TODO)
The following environment variables must be configured:
STELLAR_NETWORK: Network to use (testnetormainnet, defaults totestnet)REMITTANCE_SPLIT_CONTRACT_ID: Deployed remittance split contract address
Important: The remittance_split contract must be deployed on the specified network before the split API endpoints will work.
GET /api/split
{
"percentages": {
"savings": 30,
"bills": 25,
"insurance": 10,
"family": 20
}
}GET /api/split/calculate?amount=1000
{
"amounts": {
"savings": "300",
"bills": "250",
"insurance": "100",
"family": "200",
"remainder": "150"
}
}404 Not Found: Contract not deployed or split not configured500 Internal Server Error: RPC connection error or contract read failure400 Bad Request: Invalid parameters (calculate endpoint)
---