|
Note
|
Beta. Revenue Recognition is an Insider Preview (beta) feature. Its behavior, API and screens can change between releases. The amounts, identifiers and screens on this page are examples, some of them produced with sample data. Always check revenue figures against your own invoices before you use them to close a month, and send your feedback through Kill Bill support. |
Introduction
The Aviate Revenue Recognition module manages when revenue is recognized from the invoices that Kill Bill generates. It spreads each invoiced amount over the period in which the service is delivered, and tracks how much of it has been recognized and how much is still deferred. Finance teams get visibility into recognized vs. deferred revenue through monthly accounting periods that they can close and reopen.
Your accounting policy remains the responsibility of your finance team. Using this module does not by itself make your accounting compliant with a revenue standard such as ASC 606 or IFRS 15.
Key capabilities include:
-
Automatic revenue schedules — every eligible invoice item gets a schedule that spreads its amount over the item’s service period
-
Daily recognition — a background process recognizes revenue as each day of service is delivered
-
Accounting periods — monthly periods that are created automatically and can be closed, reopened and reported on
-
Contract-aware allocation — revenue allocated across the subscriptions of a contract using relative standalone selling prices
-
Reports — period summaries, a period-by-period waterfall of recognized and deferred revenue, revenue by plan and recognition rate
-
Schedule lookups — schedules and their daily entries by invoice item, account, subscription, plan, currency or contract
Key Concepts
Revenue Schedules and Entries
When Kill Bill generates an invoice, Aviate creates one revenue schedule for each eligible invoice item. The schedule records the invoice, invoice item, account, subscription, plan and phase it came from, together with its currency, total amount, service period and recognition method. It also keeps running recognized and deferred amounts. At creation, the full amount is deferred.
Each schedule is split into dated revenue entries. An entry is recognized once its date is reached. When the full amount of a schedule has been recognized, the schedule is closed.
Recognition Methods
The recognition method depends only on the type of the invoice item. In this release it cannot be set per plan, product or customer.
| Invoice item type | Recognition method | How the amount is spread |
|---|---|---|
Recurring |
Straight-line |
Evenly, one entry per day of the service period |
Usage |
Straight-line |
Evenly, one entry per day of the item’s service period |
Fixed (for example a setup fee) |
Immediate |
One entry for the full amount on the service start date |
External charge |
Immediate |
One entry for the full amount on the service start date |
Items with a zero or negative amount, and other item types such as taxes and credits, do not get a schedule. Each invoice item has at most one schedule.
For straight-line schedules:
-
The service period runs from the item’s start date up to, but not including, its end date. A 1 January to 1 February period covers the 31 days of January.
-
The daily amount is the total divided by the number of days, rounded to nine decimal places. Monthly amounts therefore follow the number of days in each month.
-
The last day takes any rounding difference, so the entries always add up exactly to the schedule total.
-
When a contract allocation applies (see Contract Revenue Allocation), the schedule total is the allocated amount instead of the invoice item amount.
For example, an annual subscription of $1,200.00 for the period from 1 January 2026 to 1 January 2027 (365 days) gives about $3.29 per day:
| Month | Days | Recognized |
|---|---|---|
January 2026 |
31 |
$101.92 |
February 2026 |
28 |
$92.05 |
April 2026 |
30 |
$98.63 |
Full year |
365 |
$1,200.00 |
Monthly amounts are rounded to the cent, so the sum of the twelve rounded months can differ from the total by one cent.
A $500 one-time setup fee is recognized in full on its service start date.
Accounting Periods
An accounting period groups revenue entries by calendar month. The system identifies each period by a name in the format YYYY-MM (for example, 2026-04). The system assigns each revenue entry to the accounting period corresponding to the month of its date. For example, the system assigns an entry dated 2026-04-17 to the period 2026-04.
A period is either open or closed:
-
Open — the daily recognition process recognizes the period’s entries as their dates are reached.
-
Closed — the daily recognition process no longer recognizes the period’s remaining entries, and the date and user that closed it are recorded. A closed period can be reopened, which makes it open again.
Periods are created automatically, one per calendar month, as invoices are generated. You can also create a period ahead of time. Close a period at month-end once its revenue has been recognized.
|
Note
|
Note: Closing a period does not block billing. Kill Bill still accepts invoices, credits, adjustments and payments dated in a closed period. See Invoice Adjustments, Credits and Cancellations. |
Contract Revenue Allocation
When a contract covers several subscriptions (for example a subscription, an implementation service and a support plan), Aviate allocates the contract’s transaction price across them in proportion to their standalone selling prices (SSP):
-
Each subscription in the contract (a contract term) is treated as a performance obligation.
-
The SSP for each term is looked up from the SSPs you configure for its plan, phase and currency.
-
The transaction price is allocated across the terms in proportion to their SSPs.
-
Each allocated amount is recognized using the recognition method of its invoice items.
See Contract Revenue Allocation for details.
Getting Started with Revenue Recognition
Installing the Plugin
Install the Aviate plugin as described in the How to Install the Aviate Plugin guide.
Enabling Revenue Recognition
Revenue recognition is disabled by default. To enable it, start Kill Bill with the following system property:
com.killbill.billing.plugin.aviate.enableRevenueRecognition=true
The following properties control revenue recognition:
| Property | Default | Description |
|---|---|---|
|
|
Set to |
|
|
How often the recognition process runs, in seconds. |
Revenue schedules are created as invoices are generated. Enable the feature before you start billing the customers whose revenue you want to track.
For details on setting configuration properties, refer to the Kill Bill Configuration Guide.
Using Revenue Recognition APIs
Full API documentation is available at our API documentation.
All revenue recognition endpoints are under ${KB_URL}/plugins/aviate-plugin/v1/revenue. Every request needs your Aviate token (Authorization: Bearer …) and your tenant’s Kill Bill API key and secret. Parameters are passed in the query string. Send POST requests with Content-Type: application/json and an empty JSON body ({}).
Using Revenue Recognition in Aviate
Insider Preview participants get access to the Revenue Recognition screens in Aviate. The screenshots below were taken with sample data: plans, amounts, accounts and email addresses are examples. The layout can change during the preview.
| Screen | What it shows |
|---|---|
Dashboard |
Recognized and deferred revenue, recent accounting periods, and the plans with the most revenue |
Waterfall |
Recognized and deferred revenue per accounting period, filtered by period range and currency |
Periods |
Accounting periods, with their status and the close and reopen actions |
Schedules |
One row per revenue schedule, filtered by method, period, account, plan or dates. Open a schedule to see its invoice, invoice item, item type, method, service period and entries |
By Plan |
Total, recognized and deferred revenue per plan |
Rates |
The share of revenue already recognized, per method (straight line or immediate) |
SSP |
Standalone selling prices per plan, phase and currency, with their source and validity dates |
Allocations |
Contract allocations: number of terms, transaction price and allocation method |
Accounting Periods Screen
-
A period is either Open or Closed.
-
An open period whose end date has passed is flagged Overdue. This is a reminder to close it, not a separate status.
-
The Close action is offered on the oldest open period whose end date has passed, so months are closed in order.
-
The Reopen action is offered on closed periods.
-
Closed By shows who closed the period.
Recognition Rates Screen
This screen compares straight-line and immediate revenue: number of schedules, total, recognized and deferred amounts, and the average number of days since invoicing.
How Revenue Is Recognized
Schedule Creation
When Kill Bill generates an invoice, Aviate creates a revenue schedule for each eligible invoice item and generates its entries (see Recognition Methods). It also creates the monthly accounting periods those entries fall into, if they do not exist yet. Creating a schedule does not recognize any revenue.
Daily Recognition
A background process runs at the configured interval, once a day by default. Each run:
-
Recognizes every unrecognized entry dated on or before the current date (UTC) in an open period, including entries dated today.
-
Updates each affected schedule’s recognized and deferred amounts.
-
Closes a schedule once its full amount has been recognized.
Revenue belongs to the accounting period of its service date, not to the date the process ran. Revenue for April recognized by a run in May stays in April.
Recognizing Revenue for a Specific Month
In production, regular runs recognize revenue for each day of the month as it passes. Once a run executes on or after the last day of the month, the system has processed all revenue entries for that month.
The month-end workflow is:
-
Wait for a recognition run on or after the last day of the month.
-
Review the month with the period summary and the waterfall report.
-
Close the period.
See Closing a Period for the steps.
Running Recognition On Demand
The triggerRevenueRecognition endpoint runs recognition immediately, up to a date that you choose:
curl -X POST "${KB_URL}/plugins/aviate-plugin/v1/revenue/triggerRevenueRecognition?recognitionDate=2026-04-30" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}" \
-H "Content-Type: application/json" \
-d '{}'
| Parameter | Required | Description |
|---|---|---|
|
Yes |
Recognize entries dated on or before this date ( |
A successful request returns 204 No Content. A missing recognitionDate is rejected with recognitionDate is required.
The run works like a daily run, except that it uses recognitionDate instead of the current date:
-
It recognizes every unrecognized entry dated on or before
recognitionDatein an open period, and updates and closes schedules in the same way. -
It applies to all accounts of the tenant. It cannot be limited to an account, a contract or a single month.
-
A
recognitionDatein the future recognizes revenue for service that has not been delivered yet. -
Recognized entries cannot be reverted. Reopening a period does not change entries that were already recognized.
-
Do not run it at the same time as the scheduled recognition run.
Managing Accounting Periods
Creating a Period
Periods are created automatically, but you can create one ahead of time. All three parameters are required. The name must be unique, and the end date cannot be before the start date. A successful request returns 201 Created.
curl -X POST "${KB_URL}/plugins/aviate-plugin/v1/revenue/periods?periodName=2026-05&startDate=2026-05-01&endDate=2026-05-31" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}" \
-H "Content-Type: application/json" \
-d '{}'
|
Note
|
Note: Revenue entries are assigned to periods by name. Use the YYYY-MM format with the first and last day of the month. A period with any other name receives no revenue entries.
|
Listing Periods
Add closed=true or closed=false to list only closed or only open periods.
curl "${KB_URL}/plugins/aviate-plugin/v1/revenue/periods?closed=false" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}"
To view a single period, use GET /v1/revenue/periods/{name}, for example /v1/revenue/periods/2026-04.
Each period includes:
| Field | Description |
|---|---|
|
The period name, for example |
|
The first and last day of the period |
|
|
|
When and by whom the period was closed. Empty for open periods. |
Viewing a Period Summary
The period summary returns the recognized amount, the deferred (not yet recognized) amount and the number of entries in the period, for all currencies combined:
curl "${KB_URL}/plugins/aviate-plugin/v1/revenue/periods/2026-04/summary" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}"
For one row per currency, use currencySummary instead:
curl "${KB_URL}/plugins/aviate-plugin/v1/revenue/periods/2026-04/currencySummary" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}"
If you bill in more than one currency, use the currency summary. The plain summary adds amounts in different currencies together.
Closing a Period
To close a month:
-
Check that a recognition run has taken place on or after the last day of the month.
-
Review the period summary and the waterfall report for that month.
-
Close the period. A successful close returns
204 No Content.
curl -X POST "${KB_URL}/plugins/aviate-plugin/v1/revenue/periods/2026-01/close" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}" \
-H "Content-Type: application/json" \
-d '{}'
The close is rejected if the period does not exist, is already closed, or still contains unrecognized revenue entries. In the last case the error reports how many entries remain, for example Cannot close period 2026-01: 12 unrecognized entries remain.
If the close is still rejected after a recognition run has taken place on or after the last day of the month, review the remaining entries (see Invoice Adjustments, Credits and Cancellations). You can then override this check with force=true:
curl -X POST "${KB_URL}/plugins/aviate-plugin/v1/revenue/periods/2026-01/close?force=true" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}" \
-H "Content-Type: application/json" \
-d '{}'
Closing a period does not block new invoices, credits or adjustments for that month. See Invoice Adjustments, Credits and Cancellations.
Reopening a Period
In exceptional cases, a closed period can be reopened for corrections. A successful reopen returns 204 No Content. The request is rejected if the period does not exist or is not closed.
curl -X POST "${KB_URL}/plugins/aviate-plugin/v1/revenue/periods/2026-01/reopen" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}" \
-H "Content-Type: application/json" \
-d '{}'
Reopening clears the closed date and closed-by user. Entries in the period that were not yet recognized become eligible again, and the next recognition run can pick them up. Entries that were already recognized are not changed.
Revenue Reports
Revenue Waterfall
The waterfall report shows recognized and deferred revenue for each accounting period, with one row per period and currency:
curl "${KB_URL}/plugins/aviate-plugin/v1/revenue/reports/waterfall?startPeriod=2026-01&endPeriod=2026-06¤cy=USD" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}"
All parameters are optional:
| Parameter | Description |
|---|---|
|
First period to include ( |
|
Last period to include ( |
|
Only include revenue in this currency, for example |
Each row contains the accounting period, the currency, the recognized amount, the deferred (not yet recognized) amount and the number of entries. The report is returned as JSON, so you can load it into a spreadsheet or another reporting tool.
Revenue by Plan
Total, recognized and deferred amounts and the number of schedules for each plan, across the whole tenant. Takes no parameters.
curl "${KB_URL}/plugins/aviate-plugin/v1/revenue/reports/by-plan" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}"
Recognition Rate
For each recognition method (straight-line or immediate): total amount, recognized amount, the share recognized so far and the number of schedules, across the whole tenant. Takes no parameters.
curl "${KB_URL}/plugins/aviate-plugin/v1/revenue/reports/recognition-rate" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}"
How Reports Are Calculated
Reports are built from two different sources. Their figures can differ after adjustments, credits or cancellations.
| Report | Built from | Currency handling |
|---|---|---|
Period summary |
Revenue entries in the period |
All currencies added together |
Period currency summary |
Revenue entries in the period |
One row per currency |
Revenue waterfall |
Revenue entries, by period |
One row per period and currency |
Revenue by plan |
Schedule totals |
All currencies added together |
Recognition rate |
Schedule totals, by recognition method |
All currencies added together |
In entry-based reports, "deferred" is the total of entries not yet recognized.
Contract Revenue Allocation
When a contract covers several subscriptions, Aviate uses standalone selling prices (SSP) to allocate the contract’s transaction price across them.
How Allocation Works
Each subscription in the contract is a contract term. Consider a contract with three subscriptions whose first invoice totals $15,000:
-
Enterprise subscription: $10,000/year (SSP: $10,000)
-
Implementation services: $3,000 one-time (SSP: $5,000)
-
Premium support: $2,000/year (SSP: $2,000)
-
Transaction price: $15,000
Using relative SSP allocation:
| Contract term | SSP | SSP % | Allocated Revenue |
|---|---|---|---|
Subscription |
$10,000 |
58.8% |
$8,823.53 |
Implementation |
$5,000 |
29.4% |
$4,411.76 |
Support |
$2,000 |
11.8% |
$1,764.71 |
The implementation fee ($3,000 charged) receives an allocation of $4,411.76 because relative-SSP allocation distributes the total transaction price proportionally. Any rounding difference is assigned to the last term, so the allocations add up exactly to the transaction price.
The following rules apply:
-
When allocation happens. A contract is allocated automatically when its first invoice is generated. The transaction price is the total of that invoice’s positive charges for the contract’s subscriptions. Once a contract has allocations, later invoices do not recalculate them, so later changes to SSPs do not affect it.
-
Which SSP is used. For each term, Aviate uses the most recent SSP for the term’s plan, phase and currency that is in effect on the allocation date.
-
Missing SSPs. If a term has no SSP in effect, its SSP is taken as an equal share of the transaction price (the transaction price divided by the number of terms).
-
How allocations are used. Once a contract term has an allocation, Aviate uses the allocated amount as the total of every revenue schedule created for that subscription’s invoice items, instead of the invoice item amount.
-
Allocating explicitly. You can run the allocation yourself with a transaction price of your choice (see below). Doing so replaces any existing allocation for the contract’s terms. Schedules that already exist are not recalculated.
-
Subscriptions without a contract. Subscriptions that are not part of a contract, such as self-service sign-ups, get revenue schedules and daily recognition, but no allocation.
We recommend setting explicit SSPs for every plan and phase used in contracts, so that allocations are consistent and auditable.
Setting Standalone Selling Prices
SSPs are set per plan, phase and currency, with a validity period. You can manage them on the SSP screen in Aviate, or through the API:
curl -X POST "${KB_URL}/plugins/aviate-plugin/v1/revenue/ssp?planName=implementation-services&phaseName=implementation-services-fixedterm¤cy=USD&amount=5000.00&effectiveDate=2026-01-01" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}" \
-H "Content-Type: application/json" \
-d '{}'
| Parameter | Required | Description |
|---|---|---|
|
Yes |
Kill Bill plan name |
|
Yes |
Kill Bill phase name of the plan |
|
Yes |
Currency of the SSP, for example |
|
Yes |
Standalone selling price |
|
Yes |
First day the SSP applies ( |
|
No |
Last day the SSP applies. Leave empty for no end date. |
|
No |
Free-text label for where the price comes from. Defaults to |
A successful request returns 201 Created. To list all SSPs, use GET /v1/revenue/ssp. To delete one, use DELETE /v1/revenue/ssp/{id}. Deleting an SSP removes it permanently and does not change allocations that were already made.
Allocating a Contract Explicitly
currency and transactionPrice are required. The response lists the resulting allocation for each contract term.
curl -X POST "${KB_URL}/plugins/aviate-plugin/v1/revenue/contracts/${CONTRACT_ID}/allocations?currency=USD&transactionPrice=15000.00" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}" \
-H "Content-Type: application/json" \
-d '{}'
To view a contract’s allocations without changing them, send a GET request to the same path. For each term, the result shows the plan, phase, list price, SSP, SSP ratio, allocated amount, transaction price, currency and allocation method.
Viewing Revenue Details
By Account, Subscription or Plan
List revenue schedules with any combination of these filters:
| Parameter | Description |
|---|---|
|
Schedules of one account |
|
Schedules of one subscription |
|
Schedules for one plan |
|
Schedules in one currency |
|
|
|
Schedules whose service period starts on or after this date ( |
|
Paging. |
Results are returned newest first.
curl "${KB_URL}/plugins/aviate-plugin/v1/revenue/schedules?accountId=${ACCOUNT_ID}&closed=false&limit=50" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}"
By Contract
Contract allocations and the revenue schedules of a contract are available through two calls. The contract ID is a UUID.
curl "${KB_URL}/plugins/aviate-plugin/v1/revenue/contracts/${CONTRACT_ID}/allocations" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}"
curl "${KB_URL}/plugins/aviate-plugin/v1/revenue/contracts/${CONTRACT_ID}/schedules" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}"
By Invoice Item or Schedule
Get the schedule of an invoice item, using its Kill Bill invoice item ID:
curl "${KB_URL}/plugins/aviate-plugin/v1/revenue/${INVOICE_ITEM_ID}/schedule" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}"
Get a schedule by its ID. Schedule IDs are numbers and are returned in the schedule details.
curl "${KB_URL}/plugins/aviate-plugin/v1/revenue/schedules/${SCHEDULE_ID}" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}"
List the revenue entries of a schedule, showing each entry’s date, amount, accounting period and whether it has been recognized:
curl "${KB_URL}/plugins/aviate-plugin/v1/revenue/${SCHEDULE_ID}/entriesPerSchedule" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "X-Killbill-ApiKey: ${API_KEY}" \
-H "X-Killbill-ApiSecret: ${API_SECRET}"
Business Rules and Constraints
Recognition
-
Recognition follows the service dates on the invoice item, not the invoice date or the payment date. Revenue is recognized whether or not the invoice has been paid.
-
Revenue is always assigned to calendar months. Custom fiscal calendars (for example 4-4-5 periods) are not supported.
Closed Periods
-
Closing a period does not block billing. Kill Bill still accepts invoices, credits, adjustments and payments dated in a closed period.
-
If a new invoice item has service dates in a closed period, Aviate does not create its revenue entries. If you expect back-dated invoices, reopen the affected period before the invoice is generated.
Data You Cannot Edit
Revenue schedules and entries are derived from invoices. You cannot create, edit or delete them directly.
Invoice Adjustments, Credits and Cancellations
Adjustments, credits and cancellations can change revenue schedules. How these changes affect recognized and deferred revenue, and how they interact with closed periods, is still being finalized in this preview. During the preview, review revenue for any month that contains an adjustment, a credit or a mid-period cancellation before you close it. If you are testing this module, tell us which treatment your accounting policy requires.
Not Included in This Preview
-
Accounting journal entries, or an export to an ERP or general ledger
-
A recognition method set per plan or per product
-
Equal monthly amounts with prorated first and last months. Straight-line revenue is calculated per day
-
Editing or reversing a revenue entry by hand. Schedules are created from invoices
-
Approval of a schedule before recognition
-
Blocking invoices, credits or adjustments in a closed period
Examples
Monthly Subscription
A customer is invoiced $31.00 for a monthly plan covering 2026-01-01 to 2026-02-01.
-
Aviate creates a straight-line schedule with a total of $31.00, all deferred.
-
The service period is 31 days, so Aviate creates 31 entries of $1.00, dated
2026-01-01to2026-01-31, all in period2026-01. -
After the run on
2026-01-10, $10.00 is recognized and $21.00 is deferred. -
After the run on
2026-01-31, the full $31.00 is recognized and the schedule is closed.
Quarterly Subscription Spanning Three Months
A customer is invoiced $90.00 for a quarterly plan covering 2026-01-01 to 2026-04-01, which is 90 days. The daily amount is $1.00:
| Period | Days | Revenue |
|---|---|---|
|
31 |
$31.00 |
|
28 |
$28.00 |
|
31 |
$31.00 |
Total |
90 |
$90.00 |
At the end of January, $31.00 is recognized and $59.00 is still deferred.
Rounding
A customer is invoiced $100.00 for 2026-04-01 to 2026-05-01 (30 days). Each of the first 29 entries is $3.333333333 (100 รท 30, rounded to nine decimals). The last entry, on 2026-04-30, is $3.333333343, so that the 30 entries add up to exactly $100.00.
One-Time Setup Fee
A customer is invoiced a fixed $250.00 setup fee with a service start date of 2026-04-15. Aviate creates an immediate schedule with one entry of $250.00 in period 2026-04. The first run on or after 2026-04-15 recognizes the full amount and closes the schedule.
Month-End Close
On 2026-05-02, the finance team closes April:
-
The daily run on
2026-04-30or later has recognized all April entries. -
GET /v1/revenue/periods/2026-04/summaryshows the recognized total for April with a deferred amount of 0. -
POST /v1/revenue/periods/2026-04/closereturns204 No Content. -
GET /v1/revenue/periods?closed=truenow lists2026-04with the closing date and user.
If unrecognized entries had remained in April, step 3 would have been rejected with Cannot close period 2026-04: N unrecognized entries remain. After reviewing them, the team could close the month with force=true.