SwapGate

Hosting

Single-instance hosted API: team API keys, run history, and test-mode billing webhooks. SQLite-backed; Postgres and multi-instance are out of scope.

Run it

pip install 'swapgate[hosted]'
swapgate teams create acme --history runs.db   # prints the key ONCE
swapgate serve --port 8000 --history runs.db

Or with Docker (SQLite volume at /data):

docker build -t swapgate .
docker run -d -p 8000:8000 -v sg-data:/data \
  -e STRIPE_WEBHOOK_SECRET=whsec_... \
  -e RAZORPAY_WEBHOOK_SECRET=... -e RAZORPAY_TEST_ACCOUNTS=acc_... \
  swapgate

Receipts are signed with the server key (default ~/.swapgate/host-key, override with --key). Key rotation is replace + restart: swap the key file and restart serve; previously issued receipts verify against the old key.

API

RouteAuthNotes
POST /v1/compareBearer keyInline approved suite; gate fail is 200 with passed:false.
GET /v1/runsBearer keyCaller's team rows only.
GET /v1/runs/:idBearer keyForeign ids return 404.
GET /v1/receipts/:idBearer keySigned receipt JSON.
POST /v1/billing/*/webhookSDK signatureTest-mode only; record-only ledger.

Billing containment

Webhooks verify with the real provider SDKs. Stripe events must carry livemode:false; Razorpay accounts must be allowlisted; any live-shaped credential refuses to start. There is no charge-creating code path.