Skip to content

Commit 455a680

Browse files
authored
Merge pull request killbill#609 from killbill/aviate-usage-tutorial
Add Aviate tutorial for leveraging Aviate catalog and metering APIs to recreate a AI billing use case.
2 parents f8dcb50 + 7bcd469 commit 455a680

File tree

3 files changed

+281
-1
lines changed

3 files changed

+281
-1
lines changed

html5/_main_toc.html.slim

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,9 @@ nav.sidebar-nav
365365
li.bd-sidenav-active
366366
a.nav-link href="/latest/aviate-wallet.html"
367367
| Wallet
368+
li.bd-sidenav-active
369+
a.nav-link href="/latest/aviate-usage-ai-tutorial.html"
370+
| Usage Tutorial (AI use case)
368371
li
369372
.icon-title
370373
a.bd-toc-link.main-link role="button"
Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
= Usage Tutorial - AI Use Case
2+
3+
include::{sourcedir}/aviate/includes/aviate-card.adoc[]
4+
5+
== Introduction
6+
7+
This tutorial shows how to use the Aviate APIs together with open-source Kill Bill APIs to address usage-based billing scenarios.
8+
9+
Kill Bill already supports sophisticated catalogs, usage-based plans, and automated invoicing. Aviate extends these capabilities with:
10+
11+
* A scalable metering system for capturing usage data points.
12+
* Wallet functionality integrated with Kill Bill to manage credit pools and balances.
13+
* Advanced product and plan management, also integrated with Kill Bill.
14+
15+
In this example, we simulate an AI use cases where input tokens are recorded as usage and billed periodically via paid credits.
16+
17+
== Prerequisites
18+
19+
You will need:
20+
21+
* A running Kill Bill with the Aviate plugin installed.
22+
* A valid API access tokens for all Aviate APIs calls - referred to as `ID_TOKEN`
23+
24+
== Setup: Configuring a Tenant
25+
26+
=== Step 1: Create a tenant
27+
28+
We start by creating a tenant `usage-scenario`.
29+
30+
Use the standard Kill Bill API: https://killbill.github.io/slate/tenant.html#create-a-tenant
31+
32+
[source,bash]
33+
-----
34+
curl -v -X POST -u admin:password \
35+
-H "Content-Type: application/json" \
36+
-H "Accept: application/json" \
37+
-H "X-Killbill-CreatedBy: demo" \
38+
-d '{ "apiKey": "usage-scenario", "apiSecret": "usage-scenario" }' \
39+
"http://127.0.0.1:8080/1.0/kb/tenants"
40+
-----
41+
42+
=== Step 2: Create a billing meter
43+
44+
A BillingMeter defines how usage points are filtered and aggregated. Before creating a Plan with usage, a valid billing meter must exist. This is an Aviate specific abstraction that extends the default capabilities from Kill Bill open-source.
45+
46+
For reference, this uses the https://docs.killbill.io/latest/aviate-metering[aviate metering capabilities].
47+
48+
[source,bash]
49+
-----
50+
curl -X POST \
51+
-H 'Content-Type: application/json' \
52+
-H "Authorization: Bearer ${ID_TOKEN}" \
53+
-H 'X-killbill-apiKey: usage-scenario' \
54+
-H 'X-killbill-apisecret: usage-scenario' \
55+
-d '[{"name": "Input Tokens (per Million)", "code": "input-M-tokens", "eventKey": "input.tokens", "aggregationType": "SUM"}]' \
56+
http://127.0.0.1:8080/plugins/aviate-plugin/v1/metering/billingMeters
57+
-----
58+
59+
=== Step 3: Create a simple catalog with one Plan
60+
61+
The Plan includes a usage section linked to the billing meter. The usage section will look like the following:
62+
63+
* We see the billing period to be `MONTHLY`
64+
* We can see the reference to the `billingMeter#Code`
65+
* We see one tier configured with a package size of 1 million.
66+
* We see the price matrix, which in our case is set to be $2
67+
68+
[source,bash]
69+
-----
70+
"usages": [
71+
{
72+
"usageName": "usage-monthly-1",
73+
"usageType": "CONSUMABLE",
74+
"billingPeriod": "MONTHLY",
75+
"tiers": [
76+
{
77+
"tierNumber": 1,
78+
"blocks": [
79+
{
80+
"billingMeterCode": "input-M-tokens",
81+
"size": 1000000,
82+
"max": -1,
83+
"prices": [{"currency": "USD", "value": "2.0"}]
84+
}
85+
]
86+
}
87+
]
88+
}
89+
]
90+
-----
91+
92+
For reference, this uses the https://docs.killbill.io/latest/aviate-catalog-plugin[aviate catalog capabilities].
93+
94+
95+
The full payload and API call can be seen below:
96+
97+
Use aviate API: https://killbill.github.io/slate/aviate-catalog.html#create-plan-product-pricelist
98+
99+
[source,bash]
100+
-----
101+
curl -X POST \
102+
-H 'Content-Type: application/json' \
103+
-H "Authorization: Bearer ${ID_TOKEN}" \
104+
-H "X-killbill-apiKey: usage-scenario" \
105+
-H "X-killbill-apisecret: usage-scenario" \
106+
-d '{"plans":[{"name":"usage-monthly","prettyName":"Usage Monthly Scenario","recurringBillingMode":"IN_ADVANCE","pricelistName":"DEFAULT","productName":"UsageDemo","phases":[{"prettyName":"Premium Annual Evergreen","type":"EVERGREEN","durationUnit":"UNLIMITED","durationLength":-1,"usages":[{"usageName":"usage-monthly-1","usageType":"CONSUMABLE","billingPeriod":"MONTHLY","tiers":[{"tierNumber":1,"blocks":[{"billingMeterCode":"input-M-tokens","size":1000000,"max":-1,"prices":[{"currency":"USD","value":"2.0"}]}]}]}]}]}],"products":[{"name":"UsageDemo","category":"BASE"}]}' \
107+
http://127.0.0.1:8080/plugins/aviate-plugin/v1/catalog/inputData
108+
109+
-> {"catalogName":"","plans":[{"name":"usage-monthly","prettyName":"Usage Monthly Scenario","recurringBillingMode":"IN_ADVANCE","effectiveDate":"2025-05-01T00:41:30.000Z","effectiveDateForExistingSubscriptions":"","productName":"UsageDemo","pricelistName":"DEFAULT","retired":false,"phases":[{"prettyName":"Premium Annual Evergreen","type":"EVERGREEN","durationUnit":"UNLIMITED","durationLength":-1,"fixedPrices":[],"usages":[{"usageName":"usage-monthly-1","prettyName":"","usageType":"CONSUMABLE","billingPeriod":"MONTHLY","tierBlockPolicy":"","tiers":[{"tierNumber":1,"blocks":[{"billingMeterCode":"input-M-tokens","size":1000000,"max":-1,"prices":[{"currency":"USD","value":"2.000000000"}]}]}]}]}]}],"products":[{"name":"UsageDemo","prettyName":"","category":"BASE","availableForBps":[],"availableAddons":[]}]}
110+
-----
111+
112+
== Creating a Customer Account
113+
114+
=== Step 1: Create an account
115+
116+
Use the standard Kill Bill API:https://killbill.github.io/slate/account.html#create-an-account
117+
118+
[source,bash]
119+
-----
120+
curl -v -X POST -u admin:password \
121+
-H "X-Killbill-ApiKey: usage-scenario" \
122+
-H "Content-Type: application/json" \
123+
-d '{ "name": "John Doe", "email": "john.doe@somewhere.com", "currency": "USD" }' \
124+
"http://127.0.0.1:8080/1.0/kb/accounts"
125+
-----
126+
127+
=== Step 2: Add a default payment method
128+
129+
Use the standard Kill Bill API: https://killbill.github.io/slate/account.html#add-a-payment-method
130+
131+
[source,bash]
132+
-----
133+
curl -v -X POST -u admin:password \
134+
-H "X-Killbill-ApiKey: usage-scenario" \
135+
-H "Content-Type: application/json" \
136+
-d '{ "externalKey": "ExternalKey", "pluginName": "__EXTERNAL_PAYMENT__" }' \
137+
"http://127.0.0.1:8080/1.0/kb/accounts/{accountId}/paymentMethods"
138+
-----
139+
140+
Note that we did not pass the query parameter `?isDefault=true`, meaning there is no default payment method on the account.
141+
142+
=== Step 3: Create a subscription using the usage plan previously created
143+
144+
Use the standard Kill Bill API: https://apidocs.killbill.io/subscription#create-a-subscription
145+
146+
[source,bash]
147+
-----
148+
curl -v -X POST -u admin:password \
149+
-H "X-Killbill-ApiKey: usage-scenario" \
150+
-H "Content-Type: application/json" \
151+
-d '{ "accountId": "{accountId}", "planName": "usage-monthly" }' \
152+
"http://127.0.0.1:8080/1.0/kb/subscriptions"
153+
-----
154+
155+
=== Step 4: Create a wallet for the account
156+
157+
We create a wallet and initialize it with some paid initial credits, that will result in a Kill Bill invoice and a matching payment using the default payment method on the account. If somehow the payment fails, the credits are not made available; if later a new payment attempt is made and succeeds, credits become available.
158+
159+
We also configure the wallet to replenish when available credits go below `$5` and set a target amount to `$10`; this replenish the wallet to bring it back to its original level every time it drops to `$5`.
160+
161+
Finally, we also set some expiration dates on these credits as indicated in the call below.
162+
163+
For reference, this uses the https://docs.killbill.io/latest/aviate-wallet[aviate wallet capabilities]
164+
165+
[source,bash]
166+
-----
167+
curl -v -X POST \
168+
-H "Authorization: Bearer ${ID_TOKEN}" \
169+
-H "X-Killbill-ApiKey: usage-scenario" \
170+
-H 'Content-Type: application/json' \
171+
-d '{ "kbAccountId": "{accountId}", "currency": "USD", "initCredit": { "creditType": "CREDIT_PAID", "amount": "10.00", "expDate": "2025-12-31T00:00:00Z" }, "topOff": { "topOffType": "TOP_OFF_TARGET", "lowWatermark": "5.00", "amount": "10.00", "expDurationUnit": "MONTHS", "expDurationLength": 3 } }' \
172+
http://127.0.0.1:8080/plugins/aviate-plugin/v1/wallet
173+
-----
174+
175+
Note that we see a `WALLET_PAYMENT_FAILED` status because we did not pass the query parameter `?isDefault=true` when adding the payment method. The wallet was created, but the initial credits are not yet made available.
176+
177+
178+
== Recording Usage Points
179+
180+
=== Step 1: Record usage points
181+
182+
For reference, this uses the https://docs.killbill.io/latest/aviate-metering[aviate metering capabilities]
183+
184+
[source,bash]
185+
-----
186+
curl -v -X POST \
187+
-H "Authorization: Bearer ${ID_TOKEN}" \
188+
-H 'Content-Type: application/json' \
189+
-H "X-killbill-apiKey: usage-scenario" \
190+
-H "X-killbill-apisecret: usage-scenario" \
191+
-d '[{"billingMeterCode": "input-M-tokens", "subscriptionId": "{subscriptionId}", "timestamp": "2025-05-01T05:30:00.000Z", "value": 100000}]' \
192+
http://127.0.0.1:8080/plugins/aviate-plugin/v1/metering/billing/{tenantId}
193+
-----
194+
195+
=== Step 2: Fetch usage points
196+
197+
Use the standard Kill Bill API: https://apidocs.killbill.io/usage#retrieve-usage-for-a-subscription
198+
199+
[source,bash]
200+
-----
201+
curl -v -u admin:password \
202+
-H "X-Killbill-ApiKey: usage-scenario" \
203+
"http://127.0.0.1:8080/1.0/kb/usages/{subscriptionId}?startDate=2025-05-01&endDate=2025-05-31"
204+
-----
205+
206+
== Invoicing Usage
207+
208+
=== Step 1: Trigger invoice
209+
210+
Use the standard Kill Bill API: https://apidocs.killbill.io/invoice#trigger-an-invoice-run
211+
212+
[source,bash]
213+
-----
214+
curl -v -X POST -u admin:password \
215+
-H "X-Killbill-ApiKey: usage-scenario" \
216+
-H "Content-Type: application/json" \
217+
"http://127.0.0.1:8080/1.0/kb/invoices?accountId={accountId}&targetDate=2025-06-01"
218+
219+
<{"subscriptionId":"349b6a64-1b55-4285-8021-4ef70fda2266","startDate":"2025-05-01T00:00:00.000Z","endDate":"2025-05-31T00:00:00.000Z","rolledUpUnits":[{"unitType":"input.tokens","amount":2000001.0}]}
220+
-----
221+
222+
=== Step 2: Fetch invoice
223+
224+
Use the standard Kill Bill API: https://apidocs.killbill.io/invoice#retrieve-an-invoice-by-id
225+
226+
[source,bash]
227+
-----
228+
curl -v -u admin:password \
229+
-H "X-Killbill-ApiKey: usage-scenario" \
230+
"http://127.0.0.1:8080/1.0/kb/invoices/{invoiceId}"
231+
-----
232+
233+
== Payment Retry and Credit Activation
234+
235+
=== Step 1: Set default payment method
236+
237+
Use the standard Kill Bill API: https://killbill.github.io/slate/account.html#set-the-default-payment-method
238+
239+
[source,bash]
240+
-----
241+
curl -v -X PUT -u admin:password \
242+
-H "X-Killbill-ApiKey: usage-scenario" \
243+
"http://127.0.0.1:8080/1.0/kb/accounts/{accountId}/paymentMethods/{paymentMethodId}/setDefault"
244+
-----
245+
246+
=== Step 2: Retry invoice payment
247+
248+
Use the standard Kill Bill API: https://killbill.github.io/slate/invoice.html#trigger-a-payment-for-an-invoice
249+
250+
[source,bash]
251+
-----
252+
curl -v -X POST -u admin:password \
253+
-H "X-Killbill-ApiKey: usage-scenario" \
254+
-d '{ "accountId": "{accountId}", "purchasedAmount": 10, "targetInvoiceId": "{invoiceId}" }' \
255+
"http://localhost:8080/1.0/kb/invoices/{invoiceId}/payments"
256+
-----
257+
258+
=== Step 3: Fetch wallet accounts
259+
260+
https://apidocs.killbill.io/aviate-wallet#retrieve-wallets-for-user-account
261+
262+
[source,bash]
263+
-----
264+
curl -X GET \
265+
-H "Authorization: Bearer ${ID_TOKEN}" \
266+
-H 'X-Killbill-ApiKey: usage-scenario' \
267+
http://127.0.0.1:8080/plugins/aviate-plugin/v1/wallet/{accountId}
268+
-----
269+
270+
Credits will now be available for future usage invoicing. You can repeat the same steps to insert more usage points on the next billing period, recreate a future invoice and verify this is the case.
271+
272+
273+
274+
275+
276+
277+

userguide/tutorials/consumable_in_arrear.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ The calls to record usage are made per subscription, but they can include multip
121121

122122
In our example, the online store could directly make the call to Kill Bill using that API to record each video as they are consumed.
123123

124-
Note that in scenarios where the consumption is much higher (for e.g in the case of a telecom company offering cell-phone minutes), one would need to use a *metering system* that would first *aggregate* the units on a daily granularity before making the call to Kill Bill. You can check the initial implementation of our https://github.com/killbill/killbill-meter-plugin[metring module] that provides that aggregation functionality.
124+
Note that in scenarios where the consumption is much higher (for e.g in the case of a telecom company offering cell-phone minutes), one would need to use a *metering system* that would first *aggregate* the units on a daily granularity before making the call to Kill Bill. You can check the initial implementation of our https://docs.killbill.io/latest/aviate-metering[metring module] that provides that aggregation functionality.
125125

126126

127127
=== Example of a Customer Usage

0 commit comments

Comments
 (0)