API Reference
Quickstart
Create a customer, package a Plan, and record your first usage signal — start to finish.
This guide takes you from an API key to a priced usage signal in seven steps — two of them in the dashboard, since entitlements and Plans aren't available over the API yet. Every other step shows both cURL and Node.js.
You'll need
An API key (cnk_…) from Settings → API Keys. Keep it in an environment
variable — the samples below read $CLOCKNEXT_API_KEY. The Node.js tabs use
the official @clocknext/sdk client (cnk); install it
with npm install @clocknext/sdk.
Set your key
Export your key so every request can read it. Never hard-code it in source you commit.
export CLOCKNEXT_API_KEY="cnk_your_key_here"Create a customer
A customer is who you bill. Only name and email are required — everything
else is an optional profile field you can also fill in later. Here we send the
full profile so invoices render complete from day one.
curl https://payments.clocknext.com/api/v1/customers \
-H "Authorization: Bearer $CLOCKNEXT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Inc",
"email": "ops@acme.com",
"description": "AI meeting-notes startup — growth tier",
"website": "https://acme.com",
"phone": "+1 415 555 0100",
"legalName": "Acme Incorporated",
"addressLine1": "500 Market Street",
"city": "San Francisco",
"state": "CA",
"country": "United States",
"pincode": "94105",
"taxId": "US-EIN 12-3456789",
"currencyCode": "USD"
}'import { ClockNext } from "@clocknext/sdk";
const cnk = new ClockNext({ apiKey: process.env.CLOCKNEXT_API_KEY! });
const customer = await cnk.customers.create({
name: "Acme Inc",
email: "ops@acme.com",
description: "AI meeting-notes startup — growth tier",
website: "https://acme.com",
phone: "+1 415 555 0100",
legalName: "Acme Incorporated",
addressLine1: "500 Market Street",
city: "San Francisco",
state: "CA",
country: "United States",
pincode: "94105",
taxId: "US-EIN 12-3456789",
currencyCode: "USD",
});
const customerId = customer.id; // e.g. "cus_abc123"Grab the new customer's id — you'll reference it as customerId everywhere
else. The SDK returns it directly; the raw response wraps it in the
envelope's result.
Create an entitlement
Define what the customer is allowed to consume. Entitlements aren't available over the API yet — create at least one in the dashboard:
- Credits for token-tracked features
- Outcomes for work billed by result, step by step
- Units for simple counted items
- Composite to combine entitlements into one meter
- Or skip this and bill straight against the customer's Wallet
Every type has a stable agentKey except Wallet. If you create a Credit,
Outcome, Unit, or Composite, note its agentKey — you'll pass it on your
usage signal. See
Decide what they can consume for the
full walkthrough.
Package it into a Plan
Bundle the entitlement(s) from the previous step into a Plan — the thing you
actually sell — in Plans → New Plan. For each component, choose whether
it's billed in advance or in arrears. Note the Plan's id (e.g.
plan_growth) for the next step. See
Package it as a Plan for the full
walkthrough.
Purchase the plan for the customer
Put the customer on the Plan you just created. Only customerId and
planId are required. The Plan itself must be active — purchasing an
inactive one returns 400.
curl https://payments.clocknext.com/api/v1/purchases \
-H "Authorization: Bearer $CLOCKNEXT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customerId": "cus_abc123",
"planId": "plan_growth"
}'const purchase = await cnk.purchases.create({
customerId: "cus_abc123",
planId: "plan_growth",
});This starts the customer's billing cycle and charges any up-front components immediately. The customer now has an active Plan — the last prerequisite before a signal can be recorded. See Create a purchase for the full parameter list.
Record a usage signal
Meter one LLM request against that customer, now that it's on an active Plan.
Each meter type has its own route under /signal/* — pick the one that
matches the entitlement you created. The route decides the meter, so there is
no type field in the body. customerId is always required; everything else
depends on the type.
Debits the customer's USD wallet at the model's provider cost — no
agentKey needed.
curl -X POST https://payments.clocknext.com/api/v1/signal/wallet \
-H "Authorization: Bearer $CLOCKNEXT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customerId": "cus_abc123",
"member": "dana@acme.com",
"usage": {
"model": "gpt-4o",
"inputTokens": 1200,
"outputTokens": 350,
"cacheTokens": 200,
"cacheWriteTokens": 0
},
"custom": { "feature": "chat", "region": "eu" }
}'await cnk.signals.wallet({
customerId: "cus_abc123",
model: "gpt-4o",
tokens: { input: 1200, output: 350, cache: 200, cacheWrite: 0 },
member: "dana@acme.com",
custom: { feature: "chat", region: "eu" },
});Draws down a named Credit's balance, addressed by its stable agentKey.
curl -X POST https://payments.clocknext.com/api/v1/signal/credit \
-H "Authorization: Bearer $CLOCKNEXT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customerId": "cus_abc123",
"agentKey": "deep-research",
"member": "dana@acme.com",
"usage": {
"model": "gpt-4o",
"inputTokens": 1200,
"outputTokens": 350,
"cacheTokens": 200,
"cacheWriteTokens": 0
}
}'await cnk.signals.credit({
customerId: "cus_abc123",
model: "gpt-4o",
agentKey: "deep-research", // the Credit's agent key
member: "dana@acme.com",
tokens: { input: 1200, output: 350, cache: 200, cacheWrite: 0 },
});Bills per run, not per step. Every signal of one run shares a runId.
Recording a step never bills — closing the run is its own separate call, and
that call is what bills it. See
Complete outcome.
# Record a step. Every step of one run shares the same runId.
curl -X POST https://payments.clocknext.com/api/v1/signal/outcome \
-H "Authorization: Bearer $CLOCKNEXT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customerId": "cus_abc123",
"agentKey": "resolved_ticket.resolve",
"runId": "ticket_9021",
"usage": { "model": "gpt-4o", "inputTokens": 500, "outputTokens": 200 }
}'
# Close and bill the run — a separate request.
curl -X POST https://payments.clocknext.com/api/v1/signal/outcome/complete \
-H "Authorization: Bearer $CLOCKNEXT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "customerId": "cus_abc123", "runId": "ticket_9021" }'await cnk.signals.outcome({
customerId: "cus_abc123",
model: "gpt-4o",
agentKey: "resolved_ticket.resolve", // the OutcomeStep's key
runId: "ticket_9021",
tokens: { input: 500, output: 200 },
});
// Closing the run is a separate, dedicated call — never a flag on a step.
await cnk.signals.completeOutcome({
customerId: "cus_abc123",
runId: "ticket_9021",
});Units are fixed-price meters with no model and no tokens, so there is no
usage block and a caller can never post a price. quantity defaults to 1.
curl -X POST https://payments.clocknext.com/api/v1/signal/unit \
-H "Authorization: Bearer $CLOCKNEXT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customerId": "cus_abc123",
"agentKey": "seats",
"member": "dana@acme.com"
}'await cnk.signals.unit({
customerId: "cus_abc123",
agentKey: "seats", // the unit's agent key
member: "dana@acme.com",
});The platform prices the request server-side from the model's (or unit's)
live rates. Every signal is first written to a durable inbox, so the response
is usually 202 with a rawId and the price is worked out a moment later. See
Reliability for what that means for your
code.
Read it back
Confirm the signal landed on the Signals page in the dashboard — or read the customer's balances back over the API/SDK:
curl https://payments.clocknext.com/api/v1/customers/cus_abc123/balances \
-H "Authorization: Bearer $CLOCKNEXT_API_KEY"const balances = await cnk.customers.balances("cus_abc123");balances returns the customer's wallet, credit, outcome, and unit balances
under their current Plan. See
Get a customer's balances
for the full shape.
What just happened
You authenticated with a bearer key, created a billing identity, gave it something to consume and a Plan to buy it on, purchased that Plan, metered one request against it, and read the result back — all through the same base URL and the same response envelope.
Next steps
Meter by credit or outcome
Bill against a named credit balance or an outcome step instead of the wallet.
How Plans and entitlements work
The full conceptual walkthrough — entitlements, Plans, Purchases, and Signals.
Embed the customer portal
Mint a short-lived token so customers can see their own balances.