API Contracts
:::info Source
Sourced from services/billing-service/API_CONTRACTS.md in the documentation repo.
:::
1. Surfaces
- Internal REST.
- Incoming webhooks (signed).
- Outgoing webhooks (tenant-configured).
2. Versioning
/api/v1/…; additive minor via X-API-Version.
3. Endpoints
3.1 Subscriptions
POST /api/v1/subscriptions
GET /api/v1/subscriptions/{id}
PATCH /api/v1/subscriptions/{id} (quantity, plan change, pause/resume)
POST /api/v1/subscriptions/{id}/cancel
POST /api/v1/subscriptions/{id}/resume
GET /api/v1/tenants/{tid}/subscriptions
3.2 Invoices
GET /api/v1/invoices/{id}
GET /api/v1/invoices/{id}/pdf
GET /api/v1/tenants/{tid}/invoices
POST /api/v1/invoices/{id}/pay (pay outstanding invoice via saved method)
POST /api/v1/invoices/{id}/void (admin)
3.3 Payments
POST /api/v1/payments/intents (create PaymentIntent; returns client_secret)
GET /api/v1/payments/{id}
POST /api/v1/payments/{id}/refund
3.4 Payment Methods
POST /api/v1/payment-methods/setup (returns Stripe SetupIntent client_secret)
GET /api/v1/payment-methods
DELETE /api/v1/payment-methods/{id}
POST /api/v1/payment-methods/{id}/set-default
3.5 Payouts
GET /api/v1/payouts
GET /api/v1/payouts/{id}
GET /api/v1/provider/earnings
POST /api/v1/payouts/trigger (admin; manual)
3.6 Tax
GET /api/v1/tax/calculate (preview tax for cart)
GET /api/v1/tax/jurisdictions
3.7 Webhooks
POST /webhooks/stripe (incoming, Stripe-Signature header)
POST /webhooks/tax-provider (incoming if using TaxJar alt)
3.8 Marketplace commerce (EP-6 / EPIC-MKT-001 — Ghasi-EdTech monorepo)
These routes are implemented in the Ghasi-EdTech billing-service (buyer/tenant context via x-tenant-id, x-user-id; see generated services/billing-service/openapi.json in that repo).
POST /api/v1/commerce/orders
POST /api/v1/commerce/orders/{orderId}/pay
POST /api/v1/commerce/orders/{orderId}/refund
GET /api/v1/commerce/payouts
GET /api/v1/commerce/payouts/{payoutId}/statement.pdf
GET /api/v1/commerce/coupons
POST /api/v1/commerce/coupons
POST /api/v1/commerce/coupons/redeem
- Refund after pay respects
refund_deadline_at; past deadline returnsrefund.window_passed(403). - With
COMMERCE_STRICT_CURRENCY_REGION=1, order create may returnplan.currency.unsupported_in_region(422) for region/currency pairs that are not allowed. statement.pdfreturns an M2 placeholder PDF; production-grade statements are M3+.
4. Request / Response Schemas
Create Subscription
POST /api/v1/subscriptions
{
"planId": "business-monthly",
"quantities": { "seats": 100 },
"paymentMethodId": "pm_...",
"trialDays": 14,
"couponCode": "LAUNCH2026"
}
Response:
{
"data": {
"id": "sub_01H...",
"state": "trialing",
"currentPeriod": { "start": "...", "end": "..." },
"trialEnd": "...",
"itemQuantities": { "seats": 100 }
}
}
Create PaymentIntent
POST /api/v1/payments/intents
{
"orderId": "ord_01H...",
"amount": 4999000, // $49.99 in micro-units
"currency": "USD",
"paymentMethodId": "pm_..." (optional),
"metadata": { "tenantId": "...", "buyerTenantId": "..." }
}
Response:
{
"data": {
"paymentIntentId": "pi_...",
"clientSecret": "pi_..._secret_...",
"requiresAction": false
}
}
5. Error Model
validation.payment_method.invalidpayment.declined(502 — upstream)payment.insufficient_fundspayment.authentication_required(402 — 3DS)billing.plan.not_foundbilling.coupon.expired|exhausted|invalidbilling.refund.exceeds_availablebilling.tax.jurisdiction_unsupportedrate.limited
6. Webhook Security
Stripe-Signature: t=...,v1=...header.- HMAC-SHA256 with shared secret.
- 5-min timestamp window.
- Nonce cache in Redis (per-event idempotency).
- Rejected webhooks return 400 with log entry.
7. Idempotency
Idempotency-Keyrequired on all writes.- Stripe API also accepts keys; we forward ours as a prefix.
8. Rate Limits
- Payment intent creation: 30/min per user.
- Webhook incoming: no explicit limit (Stripe controls).
- Invoice queries: 300/min per user.
9. Security
- JWT
tidmust match resource tenant. - Admin-only endpoints require
billing:adminscope. - PCI: no raw card data in our API.
10. SLOs
- Payment intent creation p95 < 500ms.
- Webhook processing p95 < 200ms (critical for Stripe).
- Invoice query p95 < 200ms.