Skip to content

Billing

A contract carries a tenant's limits — one cap per metric and period — and an optional pricingHint; a device hangs off at most one. devices.active counts attached devices rather than activated ones, so an attach past the cap is refused even when nothing on the contract is live. No invoice is stored: it is folded out of the tenant's lifecycle log per call, so one period can be re-billed under a different policy.

The device entry itself belongs to register: attaching and activating write the contract link and activatedAt there, and its derived status follows from both. Each transition also goes out as BILLING_DEVICE_EVENT_CREATE over the websocket.

POSTCreate a contract/api/v1/billing/contracts
GETList contracts/api/v1/billing/contracts
GETRead a contract/api/v1/billing/contracts/:contractId
PATCHUpdate a contract/api/v1/billing/contracts/:contractId
POSTCancel a contract/api/v1/billing/contracts/:contractId/cancel
GETList a contract's devices/api/v1/billing/contracts/:contractId/devices
POSTAttach a device/api/v1/billing/contracts/:contractId/devices
DELETEDetach a device/api/v1/billing/contracts/:contractId/devices/:deviceId
POSTActivate a device/api/v1/billing/devices/:deviceId/activate
GETList device lifecycle events/api/v1/billing/device-events
GETInvoice a period/api/v1/billing/invoice
GETList usage records/api/v1/billing/usage
GETRead current usage/api/v1/billing/usage/current

Create a contract

Creates a contract, live from that moment until it is cancelled — a contract has no term. A tenant may hold several at once, and each limits entry must be unique per metric and period.

POST/api/v1/billing/contracts

Body

NameDescription
namestringDisplay name of the contract
min length 1 · max length 128
descriptionstringoptionalOptional description of what this contract includes
max length 1024
externalContractIdstringoptionalThis contract's identifier in an external system, 1–128 characters; stored and returned unchanged and never interpreted by the backend.
min length 1 · max length 128
tariffArticleNumberstringoptionalArticle number of the booked tariff, 1–128 characters; carried along with the contract but never priced from — caps sit in limits, prices in pricingHint.
min length 1 · max length 128
limitsarrayA usage limit attached to this contract
metricstringThe metric this limit applies to
min length 1
quantityintegerMaximum allowed quantity for this metric in the given period
min 0
periodenumPeriod over which the limit is measured (month, year, lifetime)
Possible values: month, year, lifetime
enforcementHow this limit is enforced — hard limits block usage when exceeded
pricingHintobjectoptionalInformational pricing details — not used for enforcement
modelenumPricing model (device-month, device-year, tier)
Possible values: device-month, device-year, tier
tierSizeintegeroptionalNumber of units per tier (tier model only)
> 0
unitPriceMonthstringoptionalPrice per unit per month as a decimal string (e.g. 0.50)
Pattern: ^\d+\.\d{1,6}$
prepaidMonthsintegeroptionalNumber of months billed upfront
> 0
tenantIdstringoptionalTenant this contract applies to — defaults to the authenticated user's tenant
Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$

Response

NameDescription
resourceIdentifierstringUnique Coldwave resource name (CRN) that identifies a resource

Errors

StatusDescriptionBody
403You do not have permission to perform this action
400The contract configuration is invalidcode: CONTRACT_INVALID, reason: string
401No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key.error: string
500The request failed for a reason that is not the caller's to fix. Safe to retry.error: string, message: string, statusCode: 50

List contracts

Lists the tenant's contracts, cancelled ones included — status is the only thing that separates them.

GET/api/v1/billing/contracts

Response

NameDescription
resourceIdentifierstringUnique Coldwave resource name (CRN) that identifies a resource
namestringDisplay name of the contract
min length 1 · max length 128
descriptionstringoptionalOptional description of what this contract includes
max length 1024
externalContractIdstringoptionalThis contract's identifier in an external system, 1–128 characters; stored and returned unchanged and never interpreted by the backend.
min length 1 · max length 128
tariffArticleNumberstringoptionalArticle number of the booked tariff, 1–128 characters; carried along with the contract but never priced from — caps sit in limits, prices in pricingHint.
min length 1 · max length 128
limitsarrayA usage limit attached to this contract
metricstringThe metric this limit applies to
min length 1
quantityintegerMaximum allowed quantity for this metric in the given period
min 0
periodenumPeriod over which the limit is measured (month, year, lifetime)
Possible values: month, year, lifetime
enforcementHow this limit is enforced — hard limits block usage when exceeded
pricingHintobjectoptionalInformational pricing details — not used for enforcement
modelenumPricing model (device-month, device-year, tier)
Possible values: device-month, device-year, tier
tierSizeintegeroptionalNumber of units per tier (tier model only)
> 0
unitPriceMonthstringoptionalPrice per unit per month as a decimal string (e.g. 0.50)
Pattern: ^\d+\.\d{1,6}$
prepaidMonthsintegeroptionalNumber of months billed upfront
> 0
statusenumCurrent status of the contract — active or cancelled
Possible values: active, cancelled
createdAtintegerUnix timestamp in milliseconds when this resource was created.
updatedAtintegerUnix timestamp in milliseconds when this resource was last modified.

Errors

StatusDescriptionBody
403You do not have permission to perform this action
401No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key.error: string
500The request failed for a reason that is not the caller's to fix. Safe to retry.error: string, message: string, statusCode: 50

Read a contract

One contract with its limits and pricing hint; the devices hanging off it are a separate read.

GET/api/v1/billing/contracts/Yk3pL7rWq2

Path Parameters

NameDescription
contractIdstringResource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID.
Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$

Response

NameDescription
resourceIdentifierstringUnique Coldwave resource name (CRN) that identifies a resource
namestringDisplay name of the contract
min length 1 · max length 128
descriptionstringoptionalOptional description of what this contract includes
max length 1024
externalContractIdstringoptionalThis contract's identifier in an external system, 1–128 characters; stored and returned unchanged and never interpreted by the backend.
min length 1 · max length 128
tariffArticleNumberstringoptionalArticle number of the booked tariff, 1–128 characters; carried along with the contract but never priced from — caps sit in limits, prices in pricingHint.
min length 1 · max length 128
limitsarrayA usage limit attached to this contract
metricstringThe metric this limit applies to
min length 1
quantityintegerMaximum allowed quantity for this metric in the given period
min 0
periodenumPeriod over which the limit is measured (month, year, lifetime)
Possible values: month, year, lifetime
enforcementHow this limit is enforced — hard limits block usage when exceeded
pricingHintobjectoptionalInformational pricing details — not used for enforcement
modelenumPricing model (device-month, device-year, tier)
Possible values: device-month, device-year, tier
tierSizeintegeroptionalNumber of units per tier (tier model only)
> 0
unitPriceMonthstringoptionalPrice per unit per month as a decimal string (e.g. 0.50)
Pattern: ^\d+\.\d{1,6}$
prepaidMonthsintegeroptionalNumber of months billed upfront
> 0
statusenumCurrent status of the contract — active or cancelled
Possible values: active, cancelled
createdAtintegerUnix timestamp in milliseconds when this resource was created.
updatedAtintegerUnix timestamp in milliseconds when this resource was last modified.

Errors

StatusDescriptionBody
403You do not have permission to perform this action
404The requested billing resource could not be found
400The request did not match the schema for this endpoint. The details field carries the specific failures.error: Validation Error
401No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key.error: string
500The request failed for a reason that is not the caller's to fix. Safe to retry.error: string, message: string, statusCode: 50

Update a contract

Writes the fields the body carries, but replaces limits as a whole — send the complete set, not just the entries that changed. status cannot be written here; cancelling has its own route.

PATCH/api/v1/billing/contracts/Yk3pL7rWq2

Path Parameters

NameDescription
contractIdstringResource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID.
Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$

Body

NameDescription
namestringoptionalDisplay name of the contract
min length 1 · max length 128
descriptionstringoptionalOptional description of what this contract includes
max length 1024
externalContractIdstringoptionalThis contract's identifier in an external system, 1–128 characters; stored and returned unchanged and never interpreted by the backend.
min length 1 · max length 128
tariffArticleNumberstringoptionalArticle number of the booked tariff, 1–128 characters; carried along with the contract but never priced from — caps sit in limits, prices in pricingHint.
min length 1 · max length 128
limitsarrayoptionalA usage limit attached to this contract
metricstringThe metric this limit applies to
min length 1
quantityintegerMaximum allowed quantity for this metric in the given period
min 0
periodenumPeriod over which the limit is measured (month, year, lifetime)
Possible values: month, year, lifetime
enforcementHow this limit is enforced — hard limits block usage when exceeded
pricingHintobjectoptionalInformational pricing details — not used for enforcement
modelenumPricing model (device-month, device-year, tier)
Possible values: device-month, device-year, tier
tierSizeintegeroptionalNumber of units per tier (tier model only)
> 0
unitPriceMonthstringoptionalPrice per unit per month as a decimal string (e.g. 0.50)
Pattern: ^\d+\.\d{1,6}$
prepaidMonthsintegeroptionalNumber of months billed upfront
> 0

Errors

StatusDescriptionBody
403You do not have permission to perform this action
404The requested billing resource could not be found
400The contract configuration is invalidcode: CONTRACT_INVALID, reason: string
401No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key.error: string
500The request failed for a reason that is not the caller's to fix. Safe to retry.error: string, message: string, statusCode: 50

Cancel a contract

Cancels the contract and ends billing for every device on it — each live device is closed out with a contract-cancelled deactivation and may no longer connect. The devices stay attached, and nothing brings the contract back to active.

POST/api/v1/billing/contracts/Yk3pL7rWq2/cancel

Path Parameters

NameDescription
contractIdstringResource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID.
Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$

Errors

StatusDescriptionBody
403You do not have permission to perform this action
404The requested billing resource could not be found
400The request did not match the schema for this endpoint. The details field carries the specific failures.error: Validation Error
401No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key.error: string
500The request failed for a reason that is not the caller's to fix. Safe to retry.error: string, message: string, statusCode: 50

List a contract's devices

The CRNs of the devices attached to this contract, activated or not — being attached does not make a device live.

GET/api/v1/billing/contracts/Yk3pL7rWq2/devices

Path Parameters

NameDescription
contractIdstringResource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID.
Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$

Response

NameDescription

Errors

StatusDescriptionBody
403You do not have permission to perform this action
404The requested billing resource could not be found
400The request did not match the schema for this endpoint. The details field carries the specific failures.error: Validation Error
401No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key.error: string
500The request failed for a reason that is not the caller's to fix. Safe to retry.error: string, message: string, statusCode: 50

Attach a device

Links the device to the contract without making it live — activation is the customer's own step. A device coming from another contract of the same tenant is swapped over but keeps its activation only if it was still live there, while an unassigned one inherits the contract's tenant and comes back under a new CRN.

POST/api/v1/billing/contracts/Yk3pL7rWq2/devices

Path Parameters

NameDescription
contractIdstringResource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID.
Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$

Body

NameDescription
deviceIdThe device to attach, named by its device id or by the IMEI printed on it.
Alternative 1stringResource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID.
Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$
Alternative 2stringThe device to attach, named by its device id or by the IMEI printed on it.
max length 16
Pattern: ^[0-9a-fA-F]+$

Response

NameDescription
resourceIdentifierstringUnique Coldwave resource name (CRN) that identifies a resource

Errors

StatusDescriptionBody
403You do not have permission to perform this action
404The requested billing resource could not be found
409The contract is cancelled and takes no further devices — attach to an active contract instead, as a cancelled one cannot be reopened.code: CONTRACT_NOT_ACTIVE
409The contract's devices.active limit is reached; it caps attached devices rather than live ones, so detach one or raise the limit before adding another.code: CONTRACT_DEVICE_LIMIT
400The request did not match the schema for this endpoint. The details field carries the specific failures.error: Validation Error
401No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key.error: string
500The request failed for a reason that is not the caller's to fix. Safe to retry.error: string, message: string, statusCode: 50

Detach a device

Removes the device from the contract and closes its billing interval. The device keeps its tenant but loses its activation, so attaching it again later needs a fresh one.

DELETE/api/v1/billing/contracts/Yk3pL7rWq2/devices/Yk3pL7rWq2

Path Parameters

NameDescription
contractIdstringResource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID.
Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$
deviceIdThe device to detach, named by its device id or IMEI; it must currently be attached to this contract.
Alternative 1stringResource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID.
Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$
Alternative 2stringThe device to detach, named by its device id or IMEI; it must currently be attached to this contract.
max length 16
Pattern: ^[0-9a-fA-F]+$

Errors

StatusDescriptionBody
403You do not have permission to perform this action
404The requested billing resource could not be found
400The request did not match the schema for this endpoint. The details field carries the specific failures.error: Validation Error
401No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key.error: string
500The request failed for a reason that is not the caller's to fix. Safe to retry.error: string, message: string, statusCode: 50

Activate a device

Starts the device's billing and is the last step before it may connect; authorisation is update on the device, so whoever activates never needs access to the contract behind it. A second call is a conflict rather than a no-op, so a double tap in a setup screen cannot move the billing start date.

POST/api/v1/billing/devices/Yk3pL7rWq2/activate

Path Parameters

NameDescription
deviceIdIdentifier of the device
Alternative 1stringResource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID.
Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$
Alternative 2stringIdentifier of the device
max length 16
Pattern: ^[0-9a-fA-F]+$

Errors

StatusDescriptionBody
403You do not have permission to perform this action
404The requested billing resource could not be found
409The device is not on an active contract, so there is nothing to activatecode: DEVICE_NOT_ATTACHED
409The device is already activecode: DEVICE_ALREADY_ACTIVE
400The request did not match the schema for this endpoint. The details field carries the specific failures.error: Validation Error
401No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key.error: string
500The request failed for a reason that is not the caller's to fix. Safe to retry.error: string, message: string, statusCode: 50

List device lifecycle events

The tenant's append-only activation and deactivation log, oldest first and capped at 1000 entries — the raw input the invoice is folded from. Narrow it with from/to, contractId and deviceId rather than paging: there is no cursor.

GET/api/v1/billing/device-events

Query Parameters

NameDescription
contractIdstringoptionalOnly events for this contract CRN
deviceIdstringoptionalOnly events for this device CRN
fromintegeroptionalOnly events at or after this Unix timestamp
tointegeroptionalOnly events at or before this Unix timestamp

Response

NameDescription
resourceIdentifierstringUnique Coldwave resource name (CRN) that identifies a resource
tenantIdstringUnique Coldwave resource name (CRN) that identifies a resource
contractIdstringUnique Coldwave resource name (CRN) that identifies a resource
deviceIdstringUnique Coldwave resource name (CRN) that identifies a resource
transitionenumDirection of the change — activated (starts billing) or deactivated (stops billing)
Possible values: activated, deactivated
reasonenumWhat caused the change (activated, detached, swapped-in, swapped-out, contract-cancelled)
Possible values: activated, detached, swapped-in, swapped-out, contract-cancelled
timestampintegerUnix timestamp in milliseconds since epoch.

Errors

StatusDescriptionBody
403You do not have permission to perform this action
400The request did not match the schema for this endpoint. The details field carries the specific failures.error: Validation Error
401No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key.error: string
500The request failed for a reason that is not the caller's to fix. Safe to retry.error: string, message: string, statusCode: 50

Invoice a period

Folds the lifecycle log into billable device-months for [from, to), one line per contract, device and calendar month, plus a total per contract priced from its pricingHint. policy has no default — whether a partial month costs a whole one is a commercial decision and is asked for on every call.

GET/api/v1/billing/invoice?from=1756684800000&to=1759276800000&policy=full-month

Query Parameters

NameDescription
fromintegerStart of the period to invoice (UTC ms, inclusive)
tointegerEnd of the period to invoice (UTC ms, exclusive)
policyenumfull-month charges a whole month for any activity; pro-rated charges the exact fraction of that calendar month; pro-rated-30 charges the monthly rate for a full month and days/30 for a partial one
Possible values: full-month, pro-rated, pro-rated-30

Response

NameDescription
policyenumThe policy the quantities were computed under
Possible values: full-month, pro-rated, pro-rated-30
fromintegerStart of the invoiced period (UTC ms, inclusive)
tointegerEnd of the invoiced period (UTC ms, exclusive)
linesarrayOne line per contract, device and calendar month with billable time
contractIdstringUnique Coldwave resource name (CRN) that identifies a resource
deviceIdstringUnique Coldwave resource name (CRN) that identifies a resource
periodStartintegerStart of the calendar month, UTC epoch milliseconds.
periodEndintegerEnd of the calendar month, exclusive, UTC epoch milliseconds.
activeMsintegerMilliseconds the device was active during this month, clipped to the requested window.
min 0
quantitynumberBillable device-months for this line — 1 under full-month, the exact share of the month under pro-rated. Under pro-rated-30 a complete calendar month costs 1 whatever its length, a partial one days/30 capped at 1.
min 0
totalsarrayPer-contract totals
contractIdstringUnique Coldwave resource name (CRN) that identifies a resource
quantitynumberSum of the contract's line quantities.
min 0
unitPriceMonthstringoptionalPrice per device-month taken from the contract's pricing hint; absent when the contract carries none.
amountMicrosintegeroptionalquantity × unitPriceMonth in integer millionths of a currency unit, absent without a unit price; divide by 1000000 to display.
min 0

Errors

StatusDescriptionBody
403You do not have permission to perform this action
400The requested period covers more lifecycle events than one invoice may fold — narrow the windowcode: INVOICE_PERIOD_TOO_LARGE, maxEvents: 50
401No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key.error: string
500The request failed for a reason that is not the caller's to fix. Safe to retry.error: string, message: string, statusCode: 50

List usage records

The tenant's individual usage records, newest first and capped at 1000; filter with metric, from and to. Nothing is aggregated — granularity does not bucket the result.

GET/api/v1/billing/usage

Query Parameters

NameDescription
metricstringoptionalFilter results by metric name
fromintegeroptionalStart of the time range (Unix timestamp, inclusive)
tointegeroptionalEnd of the time range (Unix timestamp, inclusive)
granularityoptionalenumTime bucket size for aggregation (hour, day, month)
Possible values: hour, day, month

Response

NameDescription
resourceIdentifierstringUnique Coldwave resource name (CRN) that identifies a resource
tenantIdstringUnique Coldwave resource name (CRN) that identifies a resource
contractIdstringIdentifier of the contract this usage is billed against
min length 1
metricstringName of the metric that was measured
min length 1
quantityintegerMeasured quantity
min 0
timestampintegerUnix timestamp in milliseconds since epoch.
metadictionaryoptionalAdditional key-value metadata about this usage event

Errors

StatusDescriptionBody
403You do not have permission to perform this action
400The request did not match the schema for this endpoint. The details field carries the specific failures.error: Validation Error
401No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key.error: string
500The request failed for a reason that is not the caller's to fix. Safe to retry.error: string, message: string, statusCode: 50

Read current usage

One entry per limit of the primary contract — the oldest active one — with what the running period has used so far; an empty array when the tenant holds no active contract. devices.active is counted live from the attached devices, every other metric is summed from usage records.

GET/api/v1/billing/usage/current

Response

NameDescription
metricstringName of the metric
periodenumBilling period over which usage is accumulated (month, year, lifetime)
Possible values: month, year, lifetime
quantityintegerTotal usage accumulated in the current period
min 0
limitintegerMaximum allowed quantity for this period
min 0
remainingintegerRemaining quantity before the limit is reached
periodStartintegerUnix timestamp marking the start of the current period
periodEndintegeroptionalUnix timestamp marking the end of the current period, or null for lifetime limits

Errors

StatusDescriptionBody
403You do not have permission to perform this action
401No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key.error: string
500The request failed for a reason that is not the caller's to fix. Safe to retry.error: string, message: string, statusCode: 50

Events

Published on the tenant's event stream and delivered over the websocket to every subscriber holding read on the resource the message names. resourceIdentifier is the resource the action changed; the payload is the shape below.

EventDescription
BILLING_CONTRACT_CANCELA contract was cancelled; the payload is empty — the deactivation of each device on it arrives as its own lifecycle event.
BILLING_CONTRACT_CREATEA contract was created and is live from that moment; carries the whole entry.
BILLING_CONTRACT_UPDATEFields of a contract were changed; carries only the fields the request sent.
BILLING_DEVICE_EVENT_CREATEA device was activated or deactivated on a contract — one entry appended to the log the invoice is folded from.
BILLING_USAGE_CREATEA metered request was written to the usage log, billed against the tenant's primary contract.

Contract cancelled

A contract was cancelled; the payload is empty — the deactivation of each device on it arrives as its own lifecycle event.

EVENTBILLING_CONTRACT_CANCEL

Payload

NameDescription

Contract created

A contract was created and is live from that moment; carries the whole entry.

EVENTBILLING_CONTRACT_CREATE

Payload

NameDescription
resourceIdentifierstringUnique Coldwave resource name (CRN) that identifies a resource
namestringDisplay name of the contract
min length 1 · max length 128
descriptionstringoptionalOptional description of what this contract includes
max length 1024
externalContractIdstringoptionalThis contract's identifier in an external system, 1–128 characters; stored and returned unchanged and never interpreted by the backend.
min length 1 · max length 128
tariffArticleNumberstringoptionalArticle number of the booked tariff, 1–128 characters; carried along with the contract but never priced from — caps sit in limits, prices in pricingHint.
min length 1 · max length 128
limitsarrayA usage limit attached to this contract
metricstringThe metric this limit applies to
min length 1
quantityintegerMaximum allowed quantity for this metric in the given period
min 0
periodenumPeriod over which the limit is measured (month, year, lifetime)
Possible values: month, year, lifetime
enforcementHow this limit is enforced — hard limits block usage when exceeded
pricingHintobjectoptionalInformational pricing details — not used for enforcement
modelenumPricing model (device-month, device-year, tier)
Possible values: device-month, device-year, tier
tierSizeintegeroptionalNumber of units per tier (tier model only)
> 0
unitPriceMonthstringoptionalPrice per unit per month as a decimal string (e.g. 0.50)
Pattern: ^\d+\.\d{1,6}$
prepaidMonthsintegeroptionalNumber of months billed upfront
> 0
statusenumCurrent status of the contract — active or cancelled
Possible values: active, cancelled
createdAtintegerUnix timestamp in milliseconds when this resource was created.
updatedAtintegerUnix timestamp in milliseconds when this resource was last modified.

Contract updated

Fields of a contract were changed; carries only the fields the request sent.

EVENTBILLING_CONTRACT_UPDATE

Payload

NameDescription
namestringoptionalDisplay name of the contract
min length 1 · max length 128
descriptionstringoptionalOptional description of what this contract includes
max length 1024
externalContractIdstringoptionalThis contract's identifier in an external system, 1–128 characters; stored and returned unchanged and never interpreted by the backend.
min length 1 · max length 128
tariffArticleNumberstringoptionalArticle number of the booked tariff, 1–128 characters; carried along with the contract but never priced from — caps sit in limits, prices in pricingHint.
min length 1 · max length 128
limitsarrayoptionalA usage limit attached to this contract
metricstringThe metric this limit applies to
min length 1
quantityintegerMaximum allowed quantity for this metric in the given period
min 0
periodenumPeriod over which the limit is measured (month, year, lifetime)
Possible values: month, year, lifetime
enforcementHow this limit is enforced — hard limits block usage when exceeded
pricingHintobjectoptionalInformational pricing details — not used for enforcement
modelenumPricing model (device-month, device-year, tier)
Possible values: device-month, device-year, tier
tierSizeintegeroptionalNumber of units per tier (tier model only)
> 0
unitPriceMonthstringoptionalPrice per unit per month as a decimal string (e.g. 0.50)
Pattern: ^\d+\.\d{1,6}$
prepaidMonthsintegeroptionalNumber of months billed upfront
> 0

Device billing state changed

A device was activated or deactivated on a contract — one entry appended to the log the invoice is folded from.

EVENTBILLING_DEVICE_EVENT_CREATE

Payload

NameDescription
resourceIdentifierstringUnique Coldwave resource name (CRN) that identifies a resource
tenantIdstringUnique Coldwave resource name (CRN) that identifies a resource
contractIdstringUnique Coldwave resource name (CRN) that identifies a resource
deviceIdstringUnique Coldwave resource name (CRN) that identifies a resource
transitionenumDirection of the change — activated (starts billing) or deactivated (stops billing)
Possible values: activated, deactivated
reasonenumWhat caused the change (activated, detached, swapped-in, swapped-out, contract-cancelled)
Possible values: activated, detached, swapped-in, swapped-out, contract-cancelled
timestampintegerUnix timestamp in milliseconds since epoch.

Usage recorded

A metered request was written to the usage log, billed against the tenant's primary contract.

EVENTBILLING_USAGE_CREATE

Payload

NameDescription
resourceIdentifierstringUnique Coldwave resource name (CRN) that identifies a resource
tenantIdstringUnique Coldwave resource name (CRN) that identifies a resource
contractIdstringIdentifier of the contract this usage is billed against
min length 1
metricstringName of the metric that was measured
min length 1
quantityintegerMeasured quantity
min 0
timestampintegerUnix timestamp in milliseconds since epoch.
metadictionaryoptionalAdditional key-value metadata about this usage event