billing-service/docs/api.md
Haitao Pan 886963606f
feat: add multi-source billing ingestion (#3)
Co-authored-by: Haitao Pan <manbuzhe2009@qq.com>
2026-04-12 13:51:47 +08:00

150 lines
3.5 KiB
Markdown

# billing-service API and interfaces
This document describes the current `billing-service` task API plus the
upstream and downstream interfaces it depends on.
## Service endpoints
### `GET /healthz`
Returns service health derived from the most recent collect-and-rate execution.
Example response:
```json
{
"status": "ok",
"message": ""
}
```
### `GET /v1/status`
Returns the latest in-memory job result snapshot.
Key fields:
- `job`
- `started_at`
- `finished_at`
- `processed_samples`
- `written_minutes`
- `replayed_minutes`
- `status`
- `error`
### `POST /v1/jobs/collect-and-rate`
Triggers an immediate snapshot pull from `xray-exporter`, computes minute
deltas, rates chargeable bytes, and writes replay-safe facts into PostgreSQL.
Behavior:
- method must be `POST`
- returns `200` when the run completes without a fatal service error
- returns `503` when upstream fetch or persistence fails hard enough to mark the
run unavailable
### `POST /v1/jobs/reconcile`
Triggers the same execution path as collect-and-rate, but records the job name
as `reconcile` for operational visibility.
## Upstream dependency
### `xray-exporter`
`billing-service` currently depends on a single exporter base URL and fetches:
- `GET /v1/snapshots/latest`
Minimum payload shape:
```json
{
"collected_at": "2026-04-08T12:00:00Z",
"node_id": "jp-xhttp-contabo.svc.plus",
"env": "prod",
"samples": [
{
"uuid": "uuid-1",
"email": "user@example.com",
"inbound_tag": "xhttp-premium",
"uplink_bytes_total": 1024,
"downlink_bytes_total": 2048
}
]
}
```
Required fields:
- `collected_at`
- `node_id`
- `env`
- `samples[].uuid`
- `samples[].email`
- `samples[].inbound_tag`
- `samples[].uplink_bytes_total`
- `samples[].downlink_bytes_total`
### Target upstream contract
Current production behavior remains `GET /v1/snapshots/latest`, but the target
multi-node design should evolve to:
- HTTPS transport for remote exporter pulls
- source-specific authentication
- a windowed pull API that supports catch-up and pagination
Recommended target path:
- `GET /v1/snapshots/window?since=<RFC3339>&until=<RFC3339>&limit=<n>&cursor=<token>`
Target-state expectations:
- remote pulls use `https://` exporter base URLs
- TLS verification stays enabled
- each source can be authenticated independently
- responses can be replayed safely from source checkpoints without duplicate
billing writes
## Downstream reads
User-facing reads do not go through `billing-service`. The read model is
`accounts.svc.plus`, backed by PostgreSQL.
Relevant downstream APIs:
- `GET /api/account/usage/summary`
- `GET /api/account/usage/buckets`
- `GET /api/account/billing/summary`
Read-path rules:
- `billing-service` does not expose user-facing usage or billing query APIs
- `accounts.svc.plus` reads PostgreSQL-backed usage and billing facts
- `console.svc.plus` queries `accounts.svc.plus`, not `billing-service`
## Configuration inputs
Runtime environment variables used by the current implementation:
- `EXPORTER_BASE_URL`
- `DATABASE_URL`
- `LISTEN_ADDR`
- `COLLECT_INTERVAL`
- `DEFAULT_REGION`
- `SOURCE_REVISION`
- `PRICE_PER_BYTE`
- `INITIAL_INCLUDED_QUOTA_BYTES`
- `INITIAL_BALANCE`
`DATABASE_URL` rule:
- it must point to the same `account` database that `accounts.svc.plus` uses
- on `jp-xhttp-contabo.svc.plus`, the current accounts containers use
`DB_HOST=stunnel-client`, `DB_PORT=15432`, and `DB_NAME=account`
- `billing-service` should follow that same target so user-facing reads in
`accounts.svc.plus` see the exact facts written by `billing-service`