ClocknextHelp
DocumentationAPI ReferenceMCP Tools
Dashboard

Get started

OverviewQuickstart

Core concepts

The response envelopeErrorsPaginationAsync, flushing & reliability

API reference

Record Signals POSTRecord usage logs POST
List customers GETCreate a customer POSTGet a customer GETUpdate a customer PATCHDelete a customer DELETEGet a customer's balances GETGet a customer's current plan GETList a customer's wallet transactions GETAdd a wallet transaction POSTAdjust a customer's credit balance POSTAdjust a customer's outcome balance POSTAdjust a customer's unit balance POST
List a customer's members GETAdd a member POSTUpdate a member PATCHRemove a member DELETE
List purchases GETCreate a purchase POSTGet a purchase GETUpdate a purchase's auto-payment setting PATCHCancel a purchase POST
List invoices GETGet an invoice GETMint a hosted pay link GET
List payments GETGet a payment GET
Mint a customer-portal access token POST
Usage

Record usage logs

Records one usage log against a catalogue unit, addressed by its stable `agentKey`. Units are fixed-price meters with no tokens — the price comes from the unit's catalogue configuration, so a caller can never post a price.

POST
/units

Authorization

apiKey
AuthorizationBearer <token>

Per-organisation API key from Settings → API Keys, sent as Authorization: Bearer cnk_…. Missing, unknown or expired keys return 401.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Records one usage log against a catalogue unit. There is no quantity — one call is one unit.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/units" \  -H "Content-Type: application/json" \  -d '{    "customerId": "cus_abc123",    "agentKey": "seats",    "member": "dana@acme.com"  }'
{  "statusCode": 200,  "statusDetail": {    "status": "SUCCESS",    "message": "OK"  },  "result": {    "unitUsage": {      "id": "string",      "customerId": "string",      "unit": "string",      "agentKey": "string",      "billingMode": "ADVANCE",      "remaining": 0,      "customerCost": 0,      "member": "string",      "createdAt": "2019-08-24T14:15:22Z"    }  }}
{  "statusCode": 400,  "statusDetail": {    "status": "ERROR",    "message": "Request body must be valid JSON."  },  "result": {}}
{  "statusCode": 401,  "statusDetail": {    "status": "ERROR",    "message": "Invalid API key."  },  "result": {}}
{  "statusCode": 404,  "statusDetail": {    "status": "ERROR",    "message": "No customer with id \"cus_abc123\"."  },  "result": {}}
{  "statusCode": 409,  "statusDetail": {    "status": "ERROR",    "message": "Customer \"cus_abc123\" is archived."  },  "result": {}}
{  "statusCode": 422,  "statusDetail": {    "status": "ERROR",    "message": "No credit with agent key \"summarize\" exists in this workspace."  },  "result": {}}
{  "statusCode": 500,  "statusDetail": {    "status": "ERROR",    "message": "Could not complete the request."  },  "result": {}}

Record Signals POST

Records exactly one Signal — a single metered request against a wallet, credit or outcome meter.

List customers GET

Cursor-paginated list of the organisation's customers.

customerId*string
Length1 <= length
agentKey*string

The unit's stable agent key (set when the unit was created), matched exactly (keys are lowercased). The only accepted identifier — the display name is not, so renaming a unit never redirects a live integration.

Length1 <= length
member?string

Member email; must belong to the customer.

[key: string]?|||

Pricing-metric tag. Identical to the tag on Record Signals: a pricing metric's ref id is a property NAME on this body, so a metric voice_ai is tagged by sending "voice_ai": "wbwbewj21". The value is opaque and stored verbatim; reports roll the metric up one row per distinct value, so a usage log and a Signal carrying the same tag read as one record. Scalars only; a property that names no metric is ignored, and a bad tag never fails the call.