Skip to main content

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 returns refund.window_passed (403).
  • With COMMERCE_STRICT_CURRENCY_REGION=1, order create may return plan.currency.unsupported_in_region (422) for region/currency pairs that are not allowed.
  • statement.pdf returns 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.invalid
  • payment.declined (502 — upstream)
  • payment.insufficient_funds
  • payment.authentication_required (402 — 3DS)
  • billing.plan.not_found
  • billing.coupon.expired|exhausted|invalid
  • billing.refund.exceeds_available
  • billing.tax.jurisdiction_unsupported
  • rate.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-Key required 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 tid must match resource tenant.
  • Admin-only endpoints require billing:admin scope.
  • 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.