All API routes are under /api. Authenticated routes require a valid Privy session cookie (privy-token).
Returns all invoices for the authenticated user.
Response 200
[{ "id": "...", "title": "...", "status": "PENDING", "amountUsd": "500.00", ... }]Create a new invoice.
Body
{
"title": "Website Redesign",
"clientName": "Acme Corp",
"clientEmail": "client@acme.com",
"dueDate": "2026-06-01",
"lineItems": [
{ "description": "UI Design", "quantity": 1, "unitPrice": 200 }
]
}Response 201 — created invoice with token (used for payment link).
Get a single invoice by ID (must belong to authenticated user).
Delete an invoice. Returns 400 if the invoice is already paid.
Generate a signed MoonPay widget URL for a given invoice.
Body
{ "invoiceToken": "abc123", "amountUsd": 500 }Response 200
{ "url": "https://buy.moonpay.com?..." }Receives MoonPay transaction events. Validates moonpay-signature-v2 header.
On transaction_updated with status: completed:
- Marks invoice as
PAID - Sends payment notification email to freelancer
Receives Yellow Card payment status updates.
Updates withdrawal status: PROCESSING → COMPLETED or FAILED.
Returns the authenticated user's USDC balance on Stellar.
Response 200
{ "balance": 245.50, "address": "GABC...XYZ" }Returns all withdrawals for the authenticated user.
Initiate a USDC → NGN withdrawal to the user's registered bank account.
Body
{ "amountUsdc": 100 }Response 201 — withdrawal record with status: PROCESSING.
Errors
400— insufficient balance, or profile incomplete (no bank details)
Complete user onboarding (name + bank details). Called after first login.
Body
{
"privyId": "did:privy:...",
"name": "Chidi Okeke",
"bankAccountName": "CHIDI OKEKE",
"bankAccountNo": "0123456789",
"bankCode": "058"
}Auto-cancels overdue invoices. Protected by Authorization: Bearer <CRON_SECRET>.
Response 200
{ "cancelled": 3, "cutoff": "2026-02-16T02:00:00.000Z" }