Skip to content

Billing & Ledger Service API (1.0.0)

The Billing & Ledger Service is the financial engine of the NPS Billing Platform. It manages pricing (Rates, Rate Cards), subscription configurations, allocation rules for split billing scenarios (divorced households, subsidies), charge lifecycle, and double-entry accounting ledger.

Key Concepts

Charge Lifecycle

Charges follow a strict lifecycle with immutability after invoicing:

  • PENDING → Created but not validated
  • BILLED → Validated and ready to invoice (still editable)
  • INVOICED → Invoiced (IMMUTABLE - moved to SettledCharge)
  • PAID → Paid directly without invoice
  • VOID → Cancelled

Allocation Configuration

Defines how charges are split between multiple accounts (e.g., divorced parents, subsidy agencies). Three rule types:

  • RESPONSIBLE_PARTY: Percentage-based split
  • COVERAGE_TRANSFER: Fixed amount covered (e.g., $25 subsidy per charge)
  • BILLING_CAP: Maximum amount per period

Double-Entry Ledger

All financial transactions follow the accounting equation (Debits = Credits). Journal entries are immutable once created - corrections use adjustment entries.

Monetary Values

All monetary amounts are stored as DECIMAL type in cents (e.g., 5000 = $50.00). Use DECIMAL or NUMERIC type (BigDecimal in Java) for precision and to avoid rounding errors. Never use integers or floating-point for money.

Languages
Servers
Mock server
https://docs.nelnetpay.com/_mock/apis/billing-ledger-service
UAT server
https://api.uat.nelnetpay.com/billing
Production server
https://api.nelnetpay.com/billing

Rates

Manage rate catalog (pricing for services)

Operations

RateCards

Manage rate card groupings for UI organization

Operations

Subscriptions

Manage billable entity subscriptions to rates

Operations

AllocationConfigurations

Manage charge allocation configurations for split billing

Operations

List Allocation Configurations

Request

List all allocation configurations for the authenticated merchant.

Allocation configurations define how charges are split between multiple accounts (e.g., divorced parents, household + subsidy agency).

Security
OAuth2
Query
pageinteger>= 1

Page number (1-indexed)

Default 1
Example: page=1
page_sizeinteger[ 1 .. 200 ]

Number of items per page

Default 50
Example: page_size=50
curl -i -X GET \
  'https://docs.nelnetpay.com/_mock/apis/billing-ledger-service/allocationConfigurations?page=1&page_size=50' \
  -H 'Authorization: Bearer <YOUR_TOKEN_HERE>'

Responses

Successful response

Bodyapplication/json
resultsArray of objectsrequired
results[].​idstring(uuid)required
results[].​entityIdstring(uuid)required
results[].​namestringrequired
results[].​descriptionstring
results[].​versionintegerrequired

Business version number for allocation configuration history

results[].​effectiveFromstring(date-time)
results[].​rulesArray of objectsrequired
results[].​rules[].​idstring(uuid)required
results[].​rules[].​priorityinteger>= 1required

Processing order (1 = first)

results[].​rules[].​ruleTypestringrequired

Type of allocation rule

Enum"RESPONSIBLE_PARTY""COVERAGE_TRANSFER""BILLING_CAP"
results[].​rules[].​accountIdstring(uuid)required

Reference to Account in Profile Service

results[].​rules[].​percentagenumber(double)[ 0 .. 100 ]

For RESPONSIBLE_PARTY rules

results[].​rules[].​fixedAmountinteger>= 0

For COVERAGE_TRANSFER rules (in cents)

results[].​rules[].​capAmountinteger>= 0

For BILLING_CAP rules (in cents)

results[].​rules[].​capPeriodstring

Period for billing cap calculation

Enum"DAILY""WEEKLY""MONTHLY"
results[].​rules[].​remainderHandlingstring

How to handle remainder amounts after cap

Enum"DISTRIBUTE_PROPORTIONALLY""ASSIGN_TO_PRIMARY""LEAVE_UNALLOCATED"
results[].​optimisticLockVersioninteger(int64)read-only

Optimistic locking version (managed by Hibernate @Version). Prevents concurrent update conflicts.

results[].​createdAtstring(date-time)required
results[].​updatedAtstring(date-time)
paginationobjectrequired
pagination.​totalRecordsintegerrequired

Total number of records across all pages

Example: 100
pagination.​currentPageintegerrequired

Current page number (1-indexed)

Example: 1
pagination.​totalPagesintegerrequired

Total number of pages

Example: 10
pagination.​nextPageinteger or null

Next page number, null if on last page

Example: 2
pagination.​prevPageinteger or null

Previous page number, null if on first page

Example: null
Response
application/json
{ "results": [ {} ], "pagination": { "totalRecords": 100, "currentPage": 1, "totalPages": 10, "nextPage": 2, "prevPage": null } }

Create Allocation Configuration

Request

Create a new allocation configuration with rules.

Important: The total allocation percentage does NOT need to equal 100% at creation time. This allows for incremental household enrollment. Validation of 100% happens at charge creation time.

Rule Types:

  • RESPONSIBLE_PARTY - Split by percentage (e.g., Mom 50%, Dad 50%)
  • COVERAGE_TRANSFER - Fixed amount covered (e.g., subsidy covers $25 per charge)
  • BILLING_CAP - Maximum amount per period (e.g., subsidy covers up to $400/month)

Processing Order: Rules are processed in priority order (1 = first). COVERAGE_TRANSFER and BILLING_CAP typically run before RESPONSIBLE_PARTY.

Security
OAuth2
Bodyapplication/jsonrequired
namestring<= 255 charactersrequired
descriptionstring<= 1000 characters
rulesArray of objectsnon-emptyrequired
rules[].​priorityinteger>= 1required
rules[].​ruleTypestringrequired

Type of allocation rule

Enum"RESPONSIBLE_PARTY""COVERAGE_TRANSFER""BILLING_CAP"
rules[].​accountIdstring(uuid)required
rules[].​percentagenumber(double)[ 0 .. 100 ]
rules[].​fixedAmountinteger>= 0
rules[].​capAmountinteger>= 0
rules[].​capPeriodstring

Period for billing cap calculation

Enum"DAILY""WEEKLY""MONTHLY"
rules[].​remainderHandlingstring

How to handle remainder amounts after cap

Enum"DISTRIBUTE_PROPORTIONALLY""ASSIGN_TO_PRIMARY""LEAVE_UNALLOCATED"
curl -i -X POST \
  https://docs.nelnetpay.com/_mock/apis/billing-ledger-service/allocationConfigurations \
  -H 'Authorization: Bearer <YOUR_TOKEN_HERE>' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Emma - household + State Subsidy Split",
    "description": "State subsidy covers $25/charge, remainder to household",
    "rules": [
      {
        "priority": 1,
        "ruleType": "COVERAGE_TRANSFER",
        "accountId": "550e8400-e29b-41d4-a716-446655440030",
        "fixedAmount": 2500
      },
      {
        "priority": 2,
        "ruleType": "RESPONSIBLE_PARTY",
        "accountId": "550e8400-e29b-41d4-a716-446655440031",
        "percentage": 100
      }
    ]
  }'

Responses

Allocation configuration created successfully

Bodyapplication/json
idstring(uuid)required
entityIdstring(uuid)required
namestringrequired
descriptionstring
versionintegerrequired

Business version number for allocation configuration history

effectiveFromstring(date-time)
rulesArray of objectsrequired
rules[].​idstring(uuid)required
rules[].​priorityinteger>= 1required

Processing order (1 = first)

rules[].​ruleTypestringrequired

Type of allocation rule

Enum"RESPONSIBLE_PARTY""COVERAGE_TRANSFER""BILLING_CAP"
rules[].​accountIdstring(uuid)required

Reference to Account in Profile Service

rules[].​percentagenumber(double)[ 0 .. 100 ]

For RESPONSIBLE_PARTY rules

rules[].​fixedAmountinteger>= 0

For COVERAGE_TRANSFER rules (in cents)

rules[].​capAmountinteger>= 0

For BILLING_CAP rules (in cents)

rules[].​capPeriodstring

Period for billing cap calculation

Enum"DAILY""WEEKLY""MONTHLY"
rules[].​remainderHandlingstring

How to handle remainder amounts after cap

Enum"DISTRIBUTE_PROPORTIONALLY""ASSIGN_TO_PRIMARY""LEAVE_UNALLOCATED"
optimisticLockVersioninteger(int64)read-only

Optimistic locking version (managed by Hibernate @Version). Prevents concurrent update conflicts.

createdAtstring(date-time)required
updatedAtstring(date-time)
Response
application/json
{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "entityId": "156e622c-6cdf-4c27-9bc9-2f2db69919f5", "name": "string", "description": "string", "version": 0, "effectiveFrom": "2019-08-24T14:15:22Z", "rules": [ {} ], "optimisticLockVersion": 0, "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z" }

Get Allocation Configuration Details

Request

Retrieve details of a specific allocation configuration including all rules

Security
OAuth2
Path
allocationConfigIdstring(uuid)required

Unique identifier for the allocation configuration

curl -i -X GET \
  'https://docs.nelnetpay.com/_mock/apis/billing-ledger-service/allocationConfigurations/{allocationConfigId}' \
  -H 'Authorization: Bearer <YOUR_TOKEN_HERE>'

Responses

Successful response

Bodyapplication/json
idstring(uuid)required
entityIdstring(uuid)required
namestringrequired
descriptionstring
versionintegerrequired

Business version number for allocation configuration history

effectiveFromstring(date-time)
rulesArray of objectsrequired
rules[].​idstring(uuid)required
rules[].​priorityinteger>= 1required

Processing order (1 = first)

rules[].​ruleTypestringrequired

Type of allocation rule

Enum"RESPONSIBLE_PARTY""COVERAGE_TRANSFER""BILLING_CAP"
rules[].​accountIdstring(uuid)required

Reference to Account in Profile Service

rules[].​percentagenumber(double)[ 0 .. 100 ]

For RESPONSIBLE_PARTY rules

rules[].​fixedAmountinteger>= 0

For COVERAGE_TRANSFER rules (in cents)

rules[].​capAmountinteger>= 0

For BILLING_CAP rules (in cents)

rules[].​capPeriodstring

Period for billing cap calculation

Enum"DAILY""WEEKLY""MONTHLY"
rules[].​remainderHandlingstring

How to handle remainder amounts after cap

Enum"DISTRIBUTE_PROPORTIONALLY""ASSIGN_TO_PRIMARY""LEAVE_UNALLOCATED"
optimisticLockVersioninteger(int64)read-only

Optimistic locking version (managed by Hibernate @Version). Prevents concurrent update conflicts.

createdAtstring(date-time)required
updatedAtstring(date-time)
Response
application/json
{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "entityId": "156e622c-6cdf-4c27-9bc9-2f2db69919f5", "name": "string", "description": "string", "version": 0, "effectiveFrom": "2019-08-24T14:15:22Z", "rules": [ {} ], "optimisticLockVersion": 0, "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z" }

Update Allocation Configuration

Request

Update an allocation configuration (partial update).

Version Tracking: Each update increments the version. Existing charges and subscriptions retain the version from when they were created.

Security
OAuth2
Path
allocationConfigIdstring(uuid)required

Unique identifier for the allocation configuration

Bodyapplication/jsonrequired
namestring<= 255 characters
descriptionstring<= 1000 characters
rulesArray of objectsnon-empty
curl -i -X PATCH \
  'https://docs.nelnetpay.com/_mock/apis/billing-ledger-service/allocationConfigurations/{allocationConfigId}' \
  -H 'Authorization: Bearer <YOUR_TOKEN_HERE>' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "string",
    "description": "string",
    "rules": [
      {
        "priority": 1,
        "ruleType": "RESPONSIBLE_PARTY",
        "accountId": "3d07c219-0a88-45be-9cfc-91e9d095a1e9",
        "percentage": 100,
        "fixedAmount": 0,
        "capAmount": 0,
        "capPeriod": "DAILY",
        "remainderHandling": "DISTRIBUTE_PROPORTIONALLY"
      }
    ]
  }'

Responses

Allocation configuration updated successfully

Bodyapplication/json
idstring(uuid)required
entityIdstring(uuid)required
namestringrequired
descriptionstring
versionintegerrequired

Business version number for allocation configuration history

effectiveFromstring(date-time)
rulesArray of objectsrequired
rules[].​idstring(uuid)required
rules[].​priorityinteger>= 1required

Processing order (1 = first)

rules[].​ruleTypestringrequired

Type of allocation rule

Enum"RESPONSIBLE_PARTY""COVERAGE_TRANSFER""BILLING_CAP"
rules[].​accountIdstring(uuid)required

Reference to Account in Profile Service

rules[].​percentagenumber(double)[ 0 .. 100 ]

For RESPONSIBLE_PARTY rules

rules[].​fixedAmountinteger>= 0

For COVERAGE_TRANSFER rules (in cents)

rules[].​capAmountinteger>= 0

For BILLING_CAP rules (in cents)

rules[].​capPeriodstring

Period for billing cap calculation

Enum"DAILY""WEEKLY""MONTHLY"
rules[].​remainderHandlingstring

How to handle remainder amounts after cap

Enum"DISTRIBUTE_PROPORTIONALLY""ASSIGN_TO_PRIMARY""LEAVE_UNALLOCATED"
optimisticLockVersioninteger(int64)read-only

Optimistic locking version (managed by Hibernate @Version). Prevents concurrent update conflicts.

createdAtstring(date-time)required
updatedAtstring(date-time)
Response
application/json
{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "entityId": "156e622c-6cdf-4c27-9bc9-2f2db69919f5", "name": "string", "description": "string", "version": 0, "effectiveFrom": "2019-08-24T14:15:22Z", "rules": [ {} ], "optimisticLockVersion": 0, "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z" }

Delete Allocation Configuration

Request

Soft delete an allocation configuration.

Restrictions: Cannot delete if referenced by active subscriptions or unbilled charges.

Security
OAuth2
Path
allocationConfigIdstring(uuid)required

Unique identifier for the allocation configuration

curl -i -X DELETE \
  'https://docs.nelnetpay.com/_mock/apis/billing-ledger-service/allocationConfigurations/{allocationConfigId}' \
  -H 'Authorization: Bearer <YOUR_TOKEN_HERE>'

Responses

Allocation configuration deleted successfully

Response
No content

Validate Allocation Configuration

Request

Validate an allocation configuration for a specific billable entity.

Validation Checks:

  1. All accounts in allocation rules are associated with the billable entity
  2. RESPONSIBLE_PARTY rules total 100% of remaining amount
  3. No circular dependencies in rules

Use this before creating charges to catch configuration issues early.

Security
OAuth2
Path
allocationConfigIdstring(uuid)required

Unique identifier for the allocation configuration

Bodyapplication/jsonrequired
billableEntityIdstring(uuid)required

Billable entity to validate against

curl -i -X POST \
  'https://docs.nelnetpay.com/_mock/apis/billing-ledger-service/allocationConfigurations/{allocationConfigId}/validate' \
  -H 'Authorization: Bearer <YOUR_TOKEN_HERE>' \
  -H 'Content-Type: application/json' \
  -d '{
    "billableEntityId": "efd73805-0b19-4de3-9f1e-a64de8c44765"
  }'

Responses

Validation result

Bodyapplication/json
validbooleanrequired

Whether the allocation configuration is valid for the billable entity

totalPercentagenumber(double)

Total RESPONSIBLE_PARTY percentage coverage

errorsArray of objects
warningsArray of objects
Response
application/json
{ "valid": true, "totalPercentage": 0.1, "errors": [ {} ], "warnings": [ {} ] }

Charges

Manage billable charges (mutable pre-invoice state)

Operations

SettledCharges

Query settled charges (immutable post-invoice state)

Operations

Refunds

Manage refunds for invoices, charges, or standalone refunds

Operations

Adjustments

Manage manual adjustments and corrections

Operations

Ledger

Manage double-entry accounting ledger

Operations
Webhooks

Exports

Export data in CSV format for GL integrations

Operations