# Frontend Integration Test Guide (Rendi API)
This document helps frontend engineers integrate and test the deployed API.
## Base URL
Production base URL:
```text
https://rendi.co.uk/api
```
All routes below are relative to this base URL.
## Authentication Model
- Auth is token-based using Bearer tokens.
- Send token in header:
```http
Authorization: Bearer <token>
```
- A user has one active token at a time in MVP.
- Logging in again issues a new token and invalidates the previous token.
## Common Headers
```http
Content-Type: application/json
Authorization: Bearer <token> // required for protected endpoints
```
## Endpoint Summary
Public:
- `POST /signup`
- `POST /login`
Protected:
- `POST /readiness/score`
- `POST /readiness/calculate` (alias)
- `POST /finance/update`
- `POST /readiness/update-finance` (alias)
- `GET /finance/current`
- `GET /readiness/current-finance` (alias)
- `GET /readiness/history?limit=<1..100>`
## Contracts
### 1) Sign up
`POST /signup`
Request:
```json
{
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+447700900123",
"password": "secret123"
}
```
- `phone` optional
- `password` min length 8
Success (`201`):
```json
{
"message": "User registered successfully",
"token": "<token>",
"user": {
"id": 1,
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+447700900123"
}
}
```
Common errors:
- `409` duplicate email/phone
- `422` validation
### 2) Login
`POST /login`
Request:
```json
{
"identifier": "jane@example.com",
"password": "secret123"
}
```
- `identifier` can be email or phone
Success (`200`):
```json
{
"message": "Login successful",
"token": "<token>",
"user": {
"id": 1,
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+447700900123"
}
}
```
Common errors:
- `401` invalid credentials
- `422` invalid identifier format
### 3) Readiness Score
`POST /readiness/score` (or `/readiness/calculate`)
Requires Bearer token.
Request:
```json
{
"annualGrossIncome": 45000,
"savings": 15000,
"targetPropertyPrice": 250000,
"targetLocation": "Manchester",
"monthlyDebtPayments": 200
}
```
- `targetPropertyPrice` required
- `targetLocation` optional
Success (`200`):
```json
{
"userId": 1,
"targetLocation": "Manchester",
"readiness": {
"score": 58,
"status": "Getting closer",
"depositNeeded": 25000,
"depositGap": 10000,
"estimatedMonths": 18
}
}
```
Common errors:
- `401` missing/invalid token
- `422` missing `targetPropertyPrice`
### 4) Update Finance
`POST /finance/update` (or `/readiness/update-finance`)
Requires Bearer token.
Request:
```json
{
"annualGrossIncome": 52000,
"savings": 18000,
"targetLocation": "Leeds",
"existingCommitments": 350,
"targetPropertyPrice": 260000
}
```
Rules:
- `annualGrossIncome` required
- `savings` required
- `targetLocation` optional
- `existingCommitments` optional
- `targetPropertyPrice` optional only if already known for this user from earlier score/profile
Behavior:
- Calculates a new score
- Updates user current finance profile
- Adds a new readiness history record
Success (`200`):
```json
{
"message": "Finance updated and new readiness score calculated",
"userId": 1,
"targetLocation": "Leeds",
"existingCommitments": 350,
"readiness": {
"score": 74,
"status": "Nearly ready",
"depositNeeded": 26000,
"depositGap": 8000,
"estimatedMonths": 13
}
}
```
Common errors:
- `401` missing/invalid token
- `422` missing required finance fields
### 5) Current Finance Snapshot
`GET /finance/current` (or `/readiness/current-finance`)
Requires Bearer token.
Success (`200`):
```json
{
"userId": 1,
"finance": {
"annualGrossIncome": 52000,
"savings": 18000,
"targetPropertyPrice": 260000,
"targetLocation": "Leeds",
"existingCommitments": 350
},
"latestReadiness": {
"score": 74,
"status": "Nearly ready",
"depositNeeded": 26000,
"depositGap": 8000,
"estimatedMonths": 13
},
"updatedAt": "2026-03-07 14:24:22"
}
```
Common errors:
- `401` missing/invalid token
- `404` no profile yet
### 6) Readiness History
`GET /readiness/history?limit=10`
Requires Bearer token.
- `limit` optional (default 20, min 1, max 100)
Success (`200`):
```json
{
"userId": 1,
"count": 2,
"history": [
{
"id": 4,
"annualGrossIncome": 64000,
"savings": 26000,
"targetPropertyPrice": 300000,
"targetLocation": "Sheffield",
"existingCommitments": 300,
"score": 74,
"status": "Nearly ready",
"depositNeeded": 30000,
"depositGap": 4000,
"estimatedMonths": 6,
"createdAt": "2026-03-07T13:49:53+00:00"
}
]
}
```
## Frontend QA Checklist
1. Sign up a new user and store returned token.
2. Call `GET /finance/current` with token and verify it returns `404` before first score/update.
3. Call `POST /readiness/score` and verify score object renders in UI.
4. Call `GET /finance/current` and verify latest finance + latestReadiness fields match previous step.
5. Call `POST /finance/update` with changed values and verify score changes.
6. Call `GET /readiness/history` and verify new result appears at top of list.
7. Login again and verify old token fails with `401`, new token works.
8. Confirm validation errors are surfaced in UI for `422` responses.
## Error Handling Suggestions
- On `401`: clear local token and redirect to auth screen.
- On `422`: map API `error` text to inline field or form-level message.
- On `409`: show duplicate account message during signup.
## Example Frontend Token Storage
- Keep token in memory + secure storage strategy chosen by your app.
- Always attach token for protected endpoints.
- Replace stored token on each successful login.