API Reference
The PensionPortal.ai API is a REST API that exposes the same backend used by the web application. All IORP II compliance data — schemes, members, contributions, KFH appointments, ORA reports, and documents — is accessible programmatically via this API.
The API is the same service as the PensionPortal.ai web app. There is no separate API gateway. All endpoints share the same authentication, authorisation, and tenant isolation logic.
Base URL
https://your-deployment.vercel.app
For local development:
Authentication
All endpoints (except /api/health/*) require an authenticated session. See Authentication for details.
Content Type
All request and response bodies use application/json unless the endpoint accepts multipart file uploads (noted per-endpoint).
Versioning
The API is currently unversioned. Breaking changes will be announced via the Changelog before deployment.
Rate Limits
| Tier | Requests/minute | Burst |
|---|
| Standard (authenticated) | 120 req/min | 200 |
AI endpoints (/api/ai/*) | 20 req/min | 30 |
File upload (/api/contributions, /api/documents) | 10 req/min | 15 |
| Health probes | Unlimited | — |
Rate limit headers are included in every response:
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 118
X-RateLimit-Reset: 1709123456
When the limit is exceeded, the API returns 429 Too Many Requests.
All error responses follow a consistent structure:
{
"error": "Human-readable error message",
"details": { }
}
| Status | Meaning |
|---|
400 | Bad request — validation failed |
401 | Unauthenticated — session required |
403 | Forbidden — insufficient role or wrong tenant |
404 | Resource not found |
409 | Conflict — duplicate or state violation |
422 | Unprocessable — business logic rejection (e.g. empty CSV) |
429 | Rate limited |
500 | Internal server error |
503 | Service unavailable — dependency down |
Health Probes
Health endpoints do not require authentication and are safe to poll from load balancers:
| Endpoint | Purpose |
|---|
GET /api/health/live | Liveness — is the process up? |
GET /api/health/ready | Readiness — are required env vars configured? |
GET /api/health/db | Database connectivity check |
Tenant Isolation
Every authenticated request runs in a tenant context. You cannot access data belonging to another tenant — this is enforced server-side regardless of what IDs you pass in the request. See Tenancy Conventions for full details.