API Overview
Route inventory, shared conventions, and baseline response contracts.
Base path and format
- Base path:
/api - Request and response: JSON unless explicitly noted
- Authenticated routes require a valid NextAuth session
Route inventory
| Method | Route | Purpose |
|---|---|---|
* | /api/auth/[...nextauth] | Google OAuth login/logout/session |
POST | /api/groups | Create a group and owner membership |
GET | /api/groups | List groups for current user |
GET | /api/groups/[id] | Group detail with members + subscription |
POST | /api/groups/join | Join by invite code |
GET | /api/subscriptions/catalog | List active catalog services |
GET | /api/subscriptions/catalog/[id] | Service detail + split preview |
POST | /api/groups/[id]/subscription | Assign service to group |
POST | /api/billing/checkout | Create Stripe Checkout session |
GET | /api/billing/payments | Payment history for current user |
POST | /api/webhooks/stripe | Stripe event ingestion |
GET | /api/users/me | Profile + dashboard summary |
Authentication model
Most routes are protected and depend on session.user.id. Unauthenticated requests should return 401 with standardized error shape.
Error contract
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request body failed validation.",
"statusCode": 400
}
}
Shared error classes
| Code | Typical status | Meaning |
|---|---|---|
UNAUTHORIZED | 401 | Missing or invalid auth session |
FORBIDDEN | 403 | Authenticated but lacks permission |
NOT_FOUND | 404 | Resource does not exist |
VALIDATION_ERROR | 400 | Request contract invalid |
CONFLICT | 409 | Duplicate state, existing relation, etc. |
INTERNAL_ERROR | 500 | Unexpected unhandled error |