Prerequisites
You will need:
-
A running Kill Bill instance (0.24.x) and Kaui, set up as explained in the getting_started.html[Getting Started Guide].
-
cURL installed. On Windows, we recommend Git Bash to run the
curlcommands. -
A Kintsugi account, with Kill Bill connected as described in Step 5.
Overview
The Kintsugi Tax Plugin is a Kill Bill invoice plugin that delegates sales tax calculation to Kintsugi during invoice generation. On each invoice (dry-run or commit), the plugin invokes the Kintsugi API and maps the returned tax lines to TAX invoice items linked to the taxable lines.
This tutorial walks through a full end-to-end scenario: installing the plugin, configuring a tenant, syncing the catalog with Kintsugi, registering a jurisdiction, and verifying that an invoice picks up the correct tax.
How It Works
For developers, the Kintsugi plugin is implemented as an Kill Bill Invoice Plugin. It implements the getAdditionalInvoiceItems method. On each invoice (dry-run or commit), it:
-
Maps Kill Bill invoice line items and the account’s ship-to address to a tax estimate request.
-
Calls
POST /killbill/tax/estimateor/commiton the Kintsugi API. -
Maps the returned tax lines to Kill Bill
TAXinvoice items linked to the taxable lines.
Every call to Kintsugi API authenticated with two headers:
| Header | Value |
|---|---|
|
Kill Bill tenant API key (must match the Kintsugi Kill Bill connection). |
|
HMAC-SHA256 hex digest of the raw JSON request body, signed with the shared |
Behavior Notes
-
Dual deployment: for Aviate tenants, the Aviate plugin passes plugin properties on invoice generation; the optional
aviateIdTokenfills gaps via billing-account HTTP lookups. Non-Aviate tenants use custom fields only. -
HTTP/1.1: outbound calls to Kintsugi use HTTP/1.1 so request bodies match HMAC signatures reliably.
-
External charges: line items without a plan name use a default product category.
-
Retries: transient failures raise
InvoicePluginApiRetryException, retried after 1, 5, and 15 minutes. -
Zero tax:
$0tax lines are not added to the invoice.
Plugin Installation
Install the plugin using KPM:
kpm install_java_plugin kintsugi --from-source-<source_file_path>/kintsugi-plugin-0.1.0.jar --destination=<path_to_install_plugin>
Confirm the plugin is RUNNING with InvoicePluginApi listed:
curl -v \
-u admin:password \
http://127.0.0.1:8080/1.0/kb/nodesInfo
Plugin Configuration
In order to enable the Kintsugi plugin, the following property needs to be set in the Kill Bill Configuration File, or at a per-tenant level:
org.killbill.invoice.plugin=killbill-kintsugi
In addition, the Kintsugi plugin requires the following properties (configured automatically when tax collection is enabled in the Kintsugi app):
| Property | Required | Description |
|---|---|---|
|
Yes |
Kintsugi API base URL (no trailing slash), reachable from the Kill Bill JVM. |
|
Yes |
Shared secret; must match the HMAC secret on the Kintsugi Kill Bill connection. |
|
No |
Kill Bill base URL for optional Aviate billing-account lookup (default |
|
No |
Aviate JWT. When set, the plugin reads Aviate billing accounts before falling back to custom fields. Omit for non-Aviate deployments. |
Testing the Plugin
Once the plugin is installed and configured, you can use it to generate tax items. This section provides an end to end tutorial.
Step 1: Install the Plugin
Ensure that the plugin is installed as explained in the "Plugin Installation" section.
Step 2: Create a Tenant
Create a tenant tax-scenario, using the standard Create Tenant API:
curl -v -X POST -u admin:password \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-Killbill-CreatedBy: demo" \
-d '{ "apiKey": "tax-scenario", "apiSecret": "tax-scenario" }' \
"http://127.0.0.1:8080/1.0/kb/tenants"
Step 3: Enable the Kintsugi Invoice Plugin
Enable the kintsugi plugin for the tenant created above:
curl -u admin:password \
-H "X-Killbill-ApiKey: tax-scenario" \
-H "X-Killbill-ApiSecret: tax-scenario" \
-H "Content-Type: text/plain" \
-H "X-Killbill-CreatedBy: setup" \
-d '{"org.killbill.invoice.plugin":"killbill-kintsugi"}' \
"http://127.0.0.1:8080/1.0/kb/tenants/uploadPerTenantConfig"
Step 4: Set up the Catalog
Configure the catalog for the tenant. You can do this easily via the Aviate UI.
Alternatively, you can also upload an XML catalog via the Upload Catalog API:
curl -v \
-X POST \
-u admin:password \
-H "X-Killbill-ApiKey: tax-scenario" \
-H "X-Killbill-ApiSecret: tax-scenario" \
-H "Content-Type: text/xml" \
-H "Accept: application/json" \
-H "X-Killbill-CreatedBy: demo" \
-H "X-Killbill-Reason: demo" \
-H "X-Killbill-Comment: demo" \
-d '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><catalog> ... </catalog>' \
"http://127.0.0.1:8080/1.0/kb/catalog/xml"
Step 5: Add the Tenant in Kintsugi
In the Kintsugi app, click on "Data Sources" in the left nav, select "Kill Bill" as the integration and enter the following details:
-
Kill Bill base URL ( for example
https://api.killbill.dev). The URL must use HTTPS. -
Tenant API key (
tax-scenario) -
Tenant API secret (
tax-scenario) -
Admin username (
admin) -
Admin password (
password)
Kintsugi then syncs the catalog from Kill Bill. This sync typically takes 10 to 15 minutes to complete.
Step 6: Categorize the Synced Products
Once the sync completes, click on the "Products" link in the left nav. The products from the catalog configured in Step 4 appear in the Kintsugi app. Assign a tax category to each product from the Kintsugi products screen so that Kintsugi knows how to tax it.
Step 7: Enable Tax Collection
In the Kintsugi app, click on "Data Sources" in the left nav. Click the "Enable tax collection" button for the integration added in Step 5 above.
This step adds the kintsugi plugin configuration for the tenant and can be verified as follows:
curl -v \
-u admin:password \
-H "X-Killbill-ApiKey: tax-scenario" \
-H "X-Killbill-ApiSecret: tax-scenario" \
-H "Accept: application/json" \
"http://127.0.0.1:8080/1.0/kb/tenants/uploadPluginConfig/killbill-kintsugi"
Step 8: Create a Jurisdiction
In the Kintsugi app, click on "Data Sources" in the left nav. Create a jurisdiction for each region you want to collect tax in. For this tutorial, create a jurisdiction for California.
Step 9: Create an Account
Open the tax-scenario tenant in Kaui and create an account with a zip code that falls within
the jurisdiction registered in Step 8. For California, use zip code 94101.
Alternatively, you can also create an account via the Create Account API:
curl -v -X POST -u admin:password \
-H "X-Killbill-ApiKey: tax-scenario" \
-H "X-Killbill-ApiSecret: tax-scenario" \
-H "Content-Type: application/json" \
-H "X-Killbill-CreatedBy: demo" \
-d '{ "name": "John Doe", "email": "[email protected]", "currency": "USD", "address1": "123 Main Street", "city": "San Francisco", "state": "CA", "country": "US", "postalCode": "94101" }' \
"http://127.0.0.1:8080/1.0/kb/accounts"
Step 10: Create a Subscription
Create a subscription for the account either via Kaui or via the Create Subscription API:
curl -v -X POST -u admin:password \
-H "X-Killbill-ApiKey: tax-scenario" \
-H "X-Killbill-ApiSecret: tax-scenario" \
-H "Content-Type: application/json" \
-H "X-Killbill-CreatedBy: demo" \
-d '{ "accountId": "{accountId}", "planName": "{planName}" }' \
"http://127.0.0.1:8080/1.0/kb/subscriptions"
Step 11: Verify the Invoice
Check the invoices either via Kaui. Alternatively, you can retrieve the account’s invoices, using the standard Retrieve Account Invoices API:
curl -v -u admin:password \
-H "X-Killbill-ApiKey: tax-scenario" \
-H "X-Killbill-ApiSecret: tax-scenario" \
-H "Accept: application/json" \
"http://127.0.0.1:8080/1.0/kb/accounts/{accountId}/invoices"
Expected result: the invoice generated for the subscription includes a TAX line item linked
to the subscription line, computed by Kintsugi for the California jurisdiction.
If no TAX line appears, check the Kill Bill logs for Kintsugi returned N tax line(s) from
KintsugiInvoicePluginApi, and see the Troubleshooting section below.
Troubleshooting
| Symptom | Likely cause |
|---|---|
No |
The kintsugi-plugin is not configured as an invoice plugin (Step 3), the product isn’t categorized (Step 6), or the account’s zip code falls outside a registered jurisdiction (Step 8). |
|
The kintsugi-plugin is not configured as an invoice plugin (Step 3). |
Connection timeout |
Kill Bill cannot reach |
Products not showing up in Kintsugi |
The catalog sync (Step 5) hasn’t completed yet — it can take 10 to 15 minutes. |