subscription-service - API Contract¶
| Field | Value |
|---|---|
| Port | 9005 |
| Mode | CQRS + Mediator |
| Base path | /api/v1 |
| Owning sprint | Sprint 09 |
| Build status | TODO |
| Requirements | FR-13, FR-14, FR-15 (FR-16 MNP post-MVP) |
Bounded context: subscription lifecycle state machine and atomic MSISDN allocation/release. Audit mandatory.
Authentication and Authorization¶
Read and lifecycle endpoints require a valid JWT. Activation is internal (saga-driven).
Endpoints¶
| Method | Path | Auth | Idempotency | Summary |
|---|---|---|---|---|
| POST | /api/v1/subscriptions |
Internal (saga) | mandatory | Activate a subscription; allocate MSISDN. |
| GET | /api/v1/subscriptions/{id} |
JWT | - | Fetch a subscription. |
| GET | /api/v1/subscriptions |
JWT | - | List a customer's subscriptions (paged). |
| POST | /api/v1/subscriptions/{id}/suspend |
JWT | - | Suspend (e.g. non-payment). |
| POST | /api/v1/subscriptions/{id}/reactivate |
JWT | - | Reactivate a suspended subscription. |
| POST | /api/v1/subscriptions/{id}/terminate |
JWT | - | Terminate; release MSISDN. |
Events¶
| Direction | Event |
|---|---|
| Publish | subscription.activated.v1, subscription.suspended.v1, subscription.terminated.v1, subscription.activation-failed.v1, subscription.tariff-changed.v1, msisdn.allocated.v1, msisdn.released.v1 |
| Consume | payment.completed.v1 (activation / plan-change trigger), payment.failed.v1 (after grace period) |
payment.completed.v1 branching (Sprint 24 Features 24.3/24.4, design-note D1/D2)¶
The consumer fetches the order (GET /internal/orders/{id}) and branches on its persisted
orderType:
NEW_LINE- activate a new subscription (unchanged pre-24 behavior; the one-tariff-line invariant countsTARIFFitems only, so bundledADDONitems are allowed).PLAN_CHANGE-ChangeTariffCommandagainst the single tariff item'stargetSubscriptionId: re-validates existence, ownership and ACTIVE status, applies the order's pinned tariff snapshot, and publishessubscription.tariff-changed.v1(keyed by subscriptionId). A terminal failure (subscription gone / not owned / not ACTIVE / same tariff) REUSESsubscription.activation-failed.v1- a documented event-name reuse (design-note D2) - so the existing refund/cancel compensation runs with zero new consumers.ADDON- ignored entirely: standalone addon orders have no activation leg; order-service owns their fulfillment and publishesaddon.purchased.v1itself.
subscription.tariff-changed.v1 rides subscription.events as its third event type: consumers
MUST filter on the eventType header and use per-listener consumer groups, and MUST dedup on the
event's orderId (the record key is the subscriptionId - NOT unique across successive plan
changes of the same subscription).
Notes¶
- MSISDN allocation is atomic and concurrency-safe; no MSISDN is double-allocated.
- Lifecycle transitions are enforced as domain invariants; illegal transitions are rejected.
- Subscription list pagination:
page(default 0),size(default 20) and optionalsort=field,asc|desc(direction optional,descassumed; defaultcreatedAt,desc). Sortable fields:createdAt,activatedAt,status. Any other field or a malformed value returns the standard 400 validation error shape.
Reference: service-catalog, event-catalog, ADR-015.