Quickstart
Submit your first usage event and see it on an invoice in 5 minutes.
This guide walks you through the complete flow: attach a test contract if you only have a customer, list contracts, inspect pricing, submit a usage event, and verify it on the invoice.
Prerequisites
- A Lucius API key (create one in Settings > API Keys in the dashboard)
- A customer (dashboard Counterparties → Customers, or
POST /v1/billing/customers) — or an existing C2C contract
A customer is not a contract. GET /v1/billing/contracts is empty until a C2C program exists. Uploading a PDF under Receivables is optional — you can generate a test contract from the API.
To create the customer from your system, send your own id as external_id. Only name is required. registration_number is optional and is not used to match. See Customers.
curl -X POST https://api-dev.lucius.finance/v1/billing/customers \
-H "Authorization: Bearer luc_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Acme Corp","external_id":"cust_acme"}'Step 1: Create a test contract (if the list is empty)
Pass only the dashboard customer UUID:
curl -X POST https://api-dev.lucius.finance/v1/billing/contracts \
-H "Authorization: Bearer luc_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"customer_id":"YOUR_CUSTOMER_UUID"}'Production: https://api.lucius.finance. Use customer_id, not the customer name (names can collide).
Lucius generates {slug}-test, a sample CSA PDF, and usage metrics domestic_wire ($20) and international_wire ($30), plus a $1,000 monthly minimum. The response id is what you send as external_contract_id.
Full reference: Create a sample test contract.
Step 2: List your contracts
Verify your contract is active and check which metrics it accepts.
curl https://api.lucius.finance/v1/billing/contracts \
-H "Authorization: Bearer luc_live_YOUR_KEY"const res = await fetch("https://api.lucius.finance/v1/billing/contracts", {
headers: { Authorization: "Bearer luc_live_YOUR_KEY" },
});
const data = await res.json();
console.log(data);import requests
res = requests.get(
"https://api.lucius.finance/v1/billing/contracts",
headers={"Authorization": "Bearer luc_live_YOUR_KEY"},
)
print(res.json())Response:
{
"object": "list",
"data": [
{
"object": "contract",
"id": "acme-corp-2026",
"customer_name": "Acme Corp",
"status": "active",
"currency": "USD",
"billing_cadence": "monthly",
"metrics": ["revenue_amount_invoiced"]
}
],
"has_more": false,
"total_count": 1
}Note the id and metrics fields — you'll need them to submit usage.
Step 3: Check pricing
See how your usage will be rated.
curl https://api.lucius.finance/v1/billing/contracts/acme-corp-2026/pricing \
-H "Authorization: Bearer luc_live_YOUR_KEY"const res = await fetch(
"https://api.lucius.finance/v1/billing/contracts/acme-corp-2026/pricing",
{ headers: { Authorization: "Bearer luc_live_YOUR_KEY" } },
);
const pricing = await res.json();
console.log(pricing.rules);res = requests.get(
"https://api.lucius.finance/v1/billing/contracts/acme-corp-2026/pricing",
headers={"Authorization": "Bearer luc_live_YOUR_KEY"},
)
print(res.json()["rules"])Response:
{
"object": "pricing_program",
"contract": "acme-corp-2026",
"version": 1,
"rules": [
{
"name": "Platform Subscription",
"type": "subscription",
"model": "flat",
"amount": "2000",
"frequency": "monthly"
},
{
"name": "Usage Fee",
"type": "usage",
"model": "percentage",
"rate": 0.05,
"metric": "revenue_amount_invoiced"
}
]
}The usage rule charges 5% of revenue_amount_invoiced.
Step 4: Submit usage
Submit a usage event. Each event needs a unique event_id for idempotency.
curl -X POST https://api.lucius.finance/v1/billing/usage \
-H "Authorization: Bearer luc_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"events": [{
"external_contract_id": "acme-corp-2026",
"event_id": "evt-2026-03-001",
"metric": "revenue_amount_invoiced",
"quantity": 10000,
"timestamp": "2026-03-25T12:00:00.000Z"
}]
}'const res = await fetch("https://api.lucius.finance/v1/billing/usage", {
method: "POST",
headers: {
Authorization: "Bearer luc_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
events: [{
external_contract_id: "acme-corp-2026",
event_id: "evt-2026-03-001",
metric: "revenue_amount_invoiced",
quantity: 10000,
timestamp: "2026-03-25T12:00:00.000Z",
}],
}),
});
const result = await res.json();
console.log(result);res = requests.post(
"https://api.lucius.finance/v1/billing/usage",
headers={
"Authorization": "Bearer luc_live_YOUR_KEY",
"Content-Type": "application/json",
},
json={
"events": [{
"external_contract_id": "acme-corp-2026",
"event_id": "evt-2026-03-001",
"metric": "revenue_amount_invoiced",
"quantity": 10000,
"timestamp": "2026-03-25T12:00:00.000Z",
}]
},
)
print(res.json())Response:
{
"accepted": 1,
"rejected": 0,
"events": [{ "event_id": "evt-2026-03-001", "status": "accepted" }]
}The event was accepted, rated at 10,000 × 5% = $500.00, and the draft invoice was updated.
To send volume plus a fee you already calculated (maker/taker exceptions, waivers), add fee_amount. That value is billed as-is; the contract rate is ignored. metric must still be on the contract.
{
"events": [{
"external_contract_id": "acme-corp-2026",
"event_id": "evt-2026-03-001-fee",
"metric": "revenue_amount_invoiced",
"quantity": 10000,
"fee_amount": 37.50,
"timestamp": "2026-03-25T12:00:00.000Z"
}]
}If metrics[] is empty, add a usage rule first — see Usage events.
Step 5: Verify the event
Confirm the event was rated by looking it up.
curl https://api.lucius.finance/v1/billing/usage/evt-2026-03-001 \
-H "Authorization: Bearer luc_live_YOUR_KEY"const res = await fetch(
"https://api.lucius.finance/v1/billing/usage/evt-2026-03-001",
{ headers: { Authorization: "Bearer luc_live_YOUR_KEY" } },
);
console.log(await res.json());res = requests.get(
"https://api.lucius.finance/v1/billing/usage/evt-2026-03-001",
headers={"Authorization": "Bearer luc_live_YOUR_KEY"},
)
print(res.json())Response:
{
"object": "usage_event",
"id": "evt-2026-03-001",
"contract": "acme-corp-2026",
"metric": "revenue_amount_invoiced",
"quantity": 10000,
"status": "rated",
"ingested_at": "2026-03-05T11:21:59.868Z"
}Status is rated — the charge has been created.
Step 6: Check the invoice
Find the invoice that includes your usage charge.
curl "https://api.lucius.finance/v1/billing/invoices/INV-2026-003" \
-H "Authorization: Bearer luc_live_YOUR_KEY"const res = await fetch(
"https://api.lucius.finance/v1/billing/invoices/INV-2026-003",
{ headers: { Authorization: "Bearer luc_live_YOUR_KEY" } },
);
console.log(await res.json());res = requests.get(
"https://api.lucius.finance/v1/billing/invoices/INV-2026-003",
headers={"Authorization": "Bearer luc_live_YOUR_KEY"},
)
print(res.json())Response:
{
"object": "invoice",
"number": "INV-2026-003",
"status": "draft",
"total": 2500,
"currency": "USD",
"billing_period": { "start": "2026-03-01", "end": "2026-03-31" },
"line_items": [
{ "description": "Platform Subscription", "quantity": 1, "unit_price": 2000, "amount": 2000 },
{ "description": "Usage Fee", "quantity": 10000, "unit_price": 0.05, "amount": 500 }
]
}The usage charge of $500.00 appears alongside the $2,000 subscription charge, totalling $2,500.
What's next?
- Authentication — API key details and security
- Idempotency — Safe retries and duplicate handling
- Pagination — Paginate through large result sets
- Usage events — Metrics,
fee_amount, rating priority - API Reference — Full endpoint documentation