Skip to content

Billing

Manages premium billing, invoices, payments, and the double-entry ledger — the financial settlement layer between the plan and its members.

Overview

The Billing service handles all money movement on the platform. When a policy activates, Billing consumes the enrollment.policy.activated event and generates the first premium invoice. Subsequent invoices are generated on each billing cycle by a scheduled job. The service processes incoming payments, applies them to open invoices, records adjustments, and maintains a double-entry ledger of all financial activity.

Charges represent amounts owed for individual coverage periods. Invoices group charges into billable units. Payments reduce the outstanding invoice balance. Adjustments handle credits, debits, and retroactive corrections. The ledger provides an immutable audit trail of all financial events. Explanation of Benefits (EOB) documents are generated from claims data and surfaced through Billing's EOB API.

Installment schedules allow members to split premium payments into smaller periodic amounts. An outbox worker ensures payment and invoice events are reliably published to Kafka even if the broker is temporarily unavailable.

Responsibilities

  • Generate premium invoices on policy activation and on each billing cycle
  • Process and record incoming premium payments
  • Manage billing adjustments (credits, debits, retroactive corrections)
  • Maintain a double-entry ledger of all financial transactions
  • Manage installment payment schedules
  • Generate and serve EOB documents for adjudicated claims
  • Publish billing events consumed by Notifications and Eligibility
  • Expose internal invoice endpoint for Claims service integration

Database

Schema: billing

TablePurpose
chargesIndividual premium charges per coverage period
invoicesGrouped invoices with status lifecycle (DRAFT → OPEN → PAID/VOID)
invoice_line_itemsLine items within an invoice linked to charges
paymentsRecorded payment transactions against invoices
adjustmentsManual and automated billing adjustments
ledger_entriesDouble-entry ledger of all financial events
outboxTransactional outbox for reliable Kafka event publishing
projection_checkpointsKafka consumer offset tracking for the enrollment projection

API Routes

MethodPathAuthDescription
GET/chargesJWTList charges (filterable)
GET/charges/{locator}JWTGet charge by locator
PATCH/charges/{locator}/voidJWTVoid a charge
GET/invoicesJWTList invoices (filterable)
GET/invoices/{locator}JWTGet invoice by locator
PATCH/invoices/{locator}/finaliseJWTFinalise a draft invoice
PATCH/invoices/{locator}/voidJWTVoid an invoice
POST/invoices/{locator}/number/generateJWTGenerate an invoice display number
POST/paymentsJWTRecord a payment
GET/paymentsJWTList payments (filterable)
GET/payments/{locator}JWTGet payment by locator
PATCH/payments/{locator}/voidJWTVoid a payment
POST/adjustmentsJWTCreate a billing adjustment
GET/adjustmentsJWTList adjustments
GET/adjustments/{locator}JWTGet adjustment by locator
PATCH/adjustments/{locator}/applyJWTApply an adjustment
PATCH/adjustments/{locator}/reverseJWTReverse an applied adjustment
GET/ledgerJWTList ledger entries
GET/ledger/{locator}JWTGet a ledger entry
GET/eobJWTList EOB documents
GET/eob/{claimLocator}JWTGet EOB for a claim
POST/installmentsJWTCreate an installment schedule
PATCH/installments/{locator}/cancelJWTCancel an installment schedule
GET/internal/invoices/{locator}InternalFetch invoice for Claims (no JWT)

Events

Publishes

TopicWhen
billing.invoice.generatedA new invoice is finalised and ready for payment
billing.payment.receivedA payment is successfully recorded
billing.payment.missedA payment due date passes without payment

Consumes

TopicAction taken
enrollment.policy.activatedGenerates first invoice and initialises billing account for the new policy

Dependencies

ServiceHow used
EnrollmentFetches policy and term details when processing billing events
ClaimsFetches claim data for EOB generation
Policy AdminFetches product pricing rules for invoice calculation

Key Design Decisions

Double-entry ledger: Every financial event (charge creation, payment receipt, adjustment) writes corresponding debit and credit entries to the ledger_entries table. This provides an audit trail and enables balance reconciliation independent of the invoice/payment tables.

EOB as a billing concern: EOB documents are generated from adjudicated claims data but surfaced through Billing's API. This keeps member financial summaries in one service rather than splitting them across Claims and Billing.

Olly Health Insurance Platform