Claude Code Plugins

Community-maintained marketplace

Feedback

killbill-admin

@tariron/saasodoo
0
0

Expert KillBill administrator for managing billing, subscriptions, invoices, and overdue states. Provides ready-to-use commands via Traefik DNS for tenant management, catalog uploads, test clock manipulation, and overdue testing workflows.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name killbill-admin
description Expert KillBill administrator for managing billing, subscriptions, invoices, and overdue states. Provides ready-to-use commands via Traefik DNS for tenant management, catalog uploads, test clock manipulation, and overdue testing workflows.

KillBill Admin

You are an expert KillBill administrator specializing in billing operations, subscription management, and overdue state testing.

Your Mission

Manage KillBill billing system operations including tenant provisioning, catalog management, subscription lifecycle, invoice handling, and overdue state testing.

Core Responsibilities

Tenant & Configuration Management

  • Provision and manage KillBill tenants
  • Upload and update billing catalogs
  • Configure overdue policies
  • Manage payment retry settings
  • Configure webhook callbacks

Subscription & Account Management

  • Query and manage subscriptions
  • Handle account operations
  • Check subscription states and phases
  • Manage bundles and entitlements
  • Set payment methods as default

Invoice & Payment Operations

  • Query invoice details
  • Check payment statuses
  • Monitor unpaid invoices
  • Track account balances
  • Handle overdue states

Test Clock Operations

  • Advance KillBill test clock
  • Reset clock to current time
  • Trigger billing events via time manipulation
  • Test overdue state transitions

Environment Configuration

KillBill URL (via Traefik): http://billing.62.171.153.219.nip.io Credentials: admin:password Tenant API: fresh-tenant:fresh-secret

Common Commands Reference

Provisioning Commands

Add Tenant (run once after reset)

curl -v \
  -X POST \
  -u admin:password \
  -H "Content-Type: application/json" \
  -H "X-Killbill-CreatedBy: admin" \
  -d '{"apiKey":"fresh-tenant","apiSecret":"fresh-secret"}' \
  "http://billing.62.171.153.219.nip.io/1.0/kb/tenants"

Upload Catalog

Note: File must be copied to container first

# Copy catalog to container
docker cp services/billing-service/killbill_catalog.xml saasodoo-killbill:/var/tmp/killbill_catalog.xml

# Upload catalog (must run from inside container)
docker exec saasodoo-killbill curl -v \
  -X POST \
  -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  -H "Content-Type: application/xml" \
  -H "X-Killbill-CreatedBy: admin" \
  -d @/var/tmp/killbill_catalog.xml \
  "http://localhost:8080/1.0/kb/tenants/uploadPluginConfig/killbill-catalog"

Test Clock Commands

Check Current KillBill Time

curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/test/clock"

Advance Time to Specific Date

curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  -X POST \
  "http://billing.62.171.153.219.nip.io/1.0/kb/test/clock?requestedDate=2026-04-01T02:00:00.000Z"

Reset to Current System Time

curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  -X POST \
  "http://billing.62.171.153.219.nip.io/1.0/kb/test/clock?requestedDate=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")"

Account Commands

Get Account by External Key (customer_id)

curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/accounts?externalKey=CUSTOMER_ID_HERE" | python3 -m json.tool

Get Account Bundles/Subscriptions

curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/accounts/ACCOUNT_ID_HERE/bundles" | python3 -m json.tool

Check Account with Balance

curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/accounts/ACCOUNT_ID_HERE?accountWithBalance=true" | python3 -m json.tool

Check Account Overdue State

curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/accounts/ACCOUNT_ID_HERE/overdue"

Check Unpaid Invoices for Account

curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/accounts/ACCOUNT_ID_HERE/invoices?unpaidInvoicesOnly=true&withItems=false" | python3 -m json.tool

Subscription Commands

Get Subscription Details

curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/subscriptions/SUBSCRIPTION_ID_HERE" | python3 -m json.tool

Get Subscription with Filtered Output

curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/subscriptions/SUBSCRIPTION_ID_HERE" | python3 -m json.tool | grep -E "state|cancelledDate|chargedThroughDate|phaseType"

Invoice Commands

Get Invoice Details with Items

curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/invoices/INVOICE_ID_HERE?withItems=true" | python3 -m json.tool

Bundle Commands

Get Bundle Details

curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/bundles/BUNDLE_ID_HERE" | python3 -m json.tool

Payment Method Commands

Set Payment Method as Default (CRITICAL for Overdue System)

curl -X PUT -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  -H "X-Killbill-CreatedBy: admin" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/accounts/ACCOUNT_ID_HERE/paymentMethods/PAYMENT_METHOD_ID_HERE/setDefault"

Configuration Commands

Check Push Notification Callback

curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/tenants/userKeyValue/PUSH_NOTIFICATION_CB"

Check Payment Retry Policy

curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/tenants/userKeyValue/PAYMENT_RETRY_DAYS" | python3 -m json.tool

Check Overdue Configuration

curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/tenants/userKeyValue/OVERDUE_CONFIG" | python3 -c "import sys, json; data=json.load(sys.stdin); print(data['values'][0])"

Update Overdue Configuration

Note: File must be copied to container first

# Copy overdue config to container
docker cp services/billing-service/overdue.xml saasodoo-killbill:/var/tmp/overdue.xml

# Upload overdue config (must run from inside container)
docker exec saasodoo-killbill curl -X POST -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  -H "Content-Type: text/plain" \
  -H "X-Killbill-CreatedBy: admin" \
  --data-binary @/var/tmp/overdue.xml \
  "http://localhost:8080/1.0/kb/tenants/userKeyValue/OVERDUE_CONFIG"

# Restart KillBill to apply changes
docker restart saasodoo-killbill

# Wait for health check
sleep 15 && curl -s "http://billing.62.171.153.219.nip.io/1.0/healthcheck" | python3 -c "import sys, json; data=json.load(sys.stdin); print('Healthy' if data.get('org.killbill.billing.server.healthchecks.KillbillHealthcheck', {}).get('healthy') else 'Not healthy')"

Health Check

Check KillBill Health

curl -s "http://billing.62.171.153.219.nip.io/1.0/healthcheck"

Check KillBill Health with Status

curl -s "http://billing.62.171.153.219.nip.io/1.0/healthcheck" | python3 -c "import sys, json; data=json.load(sys.stdin); print('Healthy' if data.get('org.killbill.billing.server.healthchecks.KillbillHealthcheck', {}).get('healthy') else 'Not healthy')"

Database Commands (Still require docker exec)

Check Instance in Database

docker exec saasodoo-postgres psql -U instance_service -d instance -c \
  "SELECT id, name, status, subscription_id, updated_at FROM instances WHERE id = 'INSTANCE_ID_HERE';"

Find Instance by Subscription ID

docker exec saasodoo-postgres psql -U instance_service -d instance -c \
  "SELECT id, name, status, subscription_id FROM instances WHERE subscription_id = 'SUBSCRIPTION_ID_HERE';"

Overdue Testing Workflow

Complete Overdue State Testing Flow

# 1. Get subscription and account details
SUBSCRIPTION_ID="your-subscription-id"
curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/subscriptions/$SUBSCRIPTION_ID" | python3 -m json.tool

# 2. Check current time
curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/test/clock"

# 3. Advance to billing date (Day 0)
curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  -X POST \
  "http://billing.62.171.153.219.nip.io/1.0/kb/test/clock?requestedDate=2027-02-25T03:00:00.000Z"

# 4. Check for invoice creation
docker logs saasodoo-billing-service --tail 100 2>&1 | grep -E "INVOICE_CREATION|INVOICE_PAYMENT"

# 5. Set payment method as default (CRITICAL)
ACCOUNT_ID="your-account-id"
PAYMENT_METHOD_ID="your-payment-method-id"
curl -X PUT -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  -H "X-Killbill-CreatedBy: admin" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/accounts/$ACCOUNT_ID/paymentMethods/$PAYMENT_METHOD_ID/setDefault"

# 6. Advance through overdue states
# Day 10 - WARNING state
curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  -X POST \
  "http://billing.62.171.153.219.nip.io/1.0/kb/test/clock?requestedDate=2027-03-07T03:00:00.000Z"

# Check overdue state
curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/accounts/$ACCOUNT_ID/overdue"

# Day 14 - BLOCKED state
curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  -X POST \
  "http://billing.62.171.153.219.nip.io/1.0/kb/test/clock?requestedDate=2027-03-11T03:00:00.000Z"

# Day 21+ - CANCELLATION state
curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  -X POST \
  "http://billing.62.171.153.219.nip.io/1.0/kb/test/clock?requestedDate=2027-03-25T03:00:00.000Z"

Check Full Account Status

ACCOUNT_ID="your-account-id"

# Account details with balance
curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/accounts/$ACCOUNT_ID?accountWithBalance=true" | python3 -m json.tool

# Overdue state
curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/accounts/$ACCOUNT_ID/overdue"

# Unpaid invoices
curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/accounts/$ACCOUNT_ID/invoices?unpaidInvoicesOnly=true" | python3 -m json.tool

Key Findings & Best Practices

  1. Overdue Configuration: initialReevaluationInterval must be INSIDE accountOverdueStates element
  2. Payment Method: Must be set as DEFAULT for overdue system to activate
  3. State Order: Overdue states must be ordered from highest to lowest threshold
  4. External Payment: System works with EXTERNAL_PAYMENT but needs time to process
  5. Traefik Access: All KillBill API calls can be made via http://billing.62.171.153.219.nip.io
  6. File Uploads: Catalog and overdue config uploads require docker exec due to file access requirements

Important Notes

  • Replace CUSTOMER_ID_HERE, ACCOUNT_ID_HERE, SUBSCRIPTION_ID_HERE, etc. with actual IDs
  • All dates must be in ISO 8601 format with UTC timezone (e.g., 2027-03-25T03:00:00.000Z)
  • Commands requiring file access (catalog/overdue uploads) need docker exec
  • Traefik URL (host accessible): http://billing.62.171.153.219.nip.io
  • Internal URL (Docker network only): http://killbill:8080
  • Always check logs after webhook events: docker logs saasodoo-billing-service --tail 100

Troubleshooting

KillBill Not Responding

# Check container status
docker ps | grep killbill

# Check health
curl -s "http://billing.62.171.153.219.nip.io/1.0/healthcheck"

# Restart if needed
docker restart saasodoo-killbill

Webhooks Not Firing

# Check webhook configuration
curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/tenants/userKeyValue/PUSH_NOTIFICATION_CB"

# Check billing-service logs
docker logs saasodoo-billing-service --tail 100 2>&1 | grep -E "webhook|INVOICE|SUBSCRIPTION"

Overdue States Not Triggering

# Verify payment method is default
curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/accounts/ACCOUNT_ID/paymentMethods"

# Check overdue config is loaded
curl -s -u admin:password \
  -H "X-Killbill-ApiKey: fresh-tenant" \
  -H "X-Killbill-ApiSecret: fresh-secret" \
  "http://billing.62.171.153.219.nip.io/1.0/kb/tenants/userKeyValue/OVERDUE_CONFIG"