File size: 1,558 Bytes
ca89452
ab740b4
 
 
 
ca89452
ab740b4
ca89452
 
 
ab740b4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
---
title: Paddock API
emoji: 🏇
colorFrom: gray
colorTo: yellow
sdk: docker
app_port: 7860
pinned: false
---

# Paddock API

Node/Express backend for a white-label horse racing betting platform. SQLite, no
external services, migrates and seeds itself on boot.

## Endpoints

| Module | Count | Base |
|---|---|---|
| Race events | 6 | `/api/race-events` |
| Odds | 3 | `/api/race-events/:id/odds` |
| Betting | 4 | `/api/bets` |
| Settlement | 5 | `/api/settlements` |
| Content | 8 | `/api/teams`, `/api/jockeys` |

Plus `/api/health`, `/api/auth/login`, `/api/me`.

## Sign in

```
POST /api/auth/login  {"email":"ops@paddock.io","password":"super"}          role 1, sees every operator
POST /api/auth/login  {"email":"admin@meridian.in","password":"meridian"}    role 2, sees its own rows
POST /api/auth/login  {"email":"admin@kingsgate.in","password":"kingsgate"}  role 2, sees its own rows
```

Send the returned token as `Authorization: Bearer <token>` on every other call.

## Notes

The multi-tenant guarantee is a SQL `WHERE` clause, not an application-layer
filter — a role-2 admin who forges another operator's id gets an empty result
set from the database rather than a row that code has to remember to reject.

Straight bets snapshot the price at placement (`struck_odds`); exotics settle
pari-mutuel from the net pool. Settlement writes payouts and the audit row in a
single transaction.

The database lives in `/tmp` and resets when the Space restarts. Point `DB_PATH`
at a mounted volume, or swap `node:sqlite` for Postgres, to persist.