Tiny TypeScript/Node.js API for browsing bank branches. Designed to be easy for a frontend/mobile client to consume.
- Node.js + TypeScript
- Express
- Zod for input validation
- Jest + Supertest for tests
- Optional Firebase Cloud Function wrapper
npm install
npm run devServer runs on http://localhost:7000 by default.
npm test
npm run build
npm startA Postman collection is included at postman/branches_api.postman_collection.json.
- Import it into Postman
- Ensure
baseUrlis set (default:http://localhost:7000) - Run the requests (the pagination request stores a
branchIdvariable for the/branches/:idrequest) - The collection also includes ATM-related branch filters and
/branches/:id/atmsrequests
GET /health
Response:
{ "status": "ok" }GET /branches
Query parameters:
city(string, optional): filter by city (case-insensitive exact match)open(true|false, optional): whentrue, returns branches that are open “right now” based on today’s hoursincludeAtms(true|false, optional, defaultfalse): whentrue, embeds theatmsarray in each branch item (otherwise only ATM counts are returned)hasAtm(true|false, optional): filter branches that have (or do not have) ATMsatmDeposit(true|false, optional): filter branches that have at least one deposit-capable ATMatmAccessible(true|false, optional): filter branches that have at least one accessible ATMpage(number as string, optional, default1): must be> 0limit(number as string, optional, default20): must be1..100
Response shape:
{
"total": 1,
"page": 1,
"limit": 20,
"items": [
{
"id": "b1",
"name": "Alexanderplatz Branch",
"address": "Alexanderplatz 5",
"city": "Berlin",
"location": { "lat": 52.5219, "lon": 13.4132 },
"atmCount": 2,
"depositAtmCount": 1,
"accessibleAtmCount": 1,
"inServiceAtmCount": 1,
"hours": {
"mon": "09:00-18:00",
"tue": "09:00-18:00",
"wed": "09:00-18:00",
"thu": "09:00-18:00",
"fri": "09:00-18:00",
"sat": "10:00-16:00",
"sun": "Closed"
}
}
]
}Examples:
GET /branches?city=BerlinGET /branches?page=2&limit=10GET /branches?open=trueGET /branches?includeAtms=trueGET /branches?hasAtm=trueGET /branches?atmDeposit=true
GET /branches/:id
200: branch object404:{ "status": 404, "message": "Not found" }
GET /branches/:id/atms
Query parameters:
deposit(true|false, optional)accessible(true|false, optional)inService(true|false, optional)page/limit(same rules as branches)
Response shape:
{
"total": 2,
"page": 1,
"limit": 20,
"items": [
{
"id": "atm-b1-1",
"location": { "lat": 52.52195, "lon": 13.41315 },
"availability": "in_service",
"supportsCashWithdrawal": true,
"supportsDeposit": true,
"accessible": true
}
]
}GET /atms
This endpoint is frontend-oriented: each ATM includes the branch context needed to show it in a list/map UI.
Query parameters:
city(string, optional)near(lat,lonstring, optional): example52.5219,13.4132radiusKm(number as string, optional): requiresnear; filters results within the given radiusdeposit(true|false, optional)accessible(true|false, optional)inService(true|false, optional)page/limit(same rules as branches)
Response shape:
{
"total": 3,
"page": 1,
"limit": 20,
"items": [
{
"id": "atm-b1-1",
"location": { "lat": 52.52195, "lon": 13.41315 },
"distanceKm": 0.01,
"availability": "in_service",
"supportsCashWithdrawal": true,
"supportsDeposit": true,
"accessible": true,
"branch": {
"id": "b1",
"name": "Alexanderplatz Branch",
"address": "Alexanderplatz 5",
"city": "Berlin",
"location": { "lat": 52.5219, "lon": 13.4132 }
}
}
]
}Notes:
- When
nearis provided, items are sorted bydistanceKmascending. distanceKmis only included whennearis provided.
- Validation errors return
400with{ status: 400, message: "Validation error", details: [...] } - Unknown errors return
500with{ status: 500, message: "Internal server error" }
Branch data is loaded from a static JSON file: branches-api/src/data/branches.json.
If you want to run this as a Firebase HTTPS function, there is a wrapper at branches-api/functions/src/index.ts:
- exported function name:
api
No deployment is required for this task; local execution is sufficient.
branches-api/src/app.ts: Express app setup + routes + error handlerbranches-api/src/routes: route definitionsbranches-api/src/controllers: request handlersbranches-api/src/services: data access / business logicbranches-api/src/middleware: validation + error handlingbranches-api/src/__tests__: Jest/Supertest integration tests