Lucius API

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?

On this page