Attributes
string
Unique identifier, prefixed
umod_.string | null
What this metered product is called.
string | null
The object holding the people who consume them.
string | null
Optional property an external system identifies products by: a SKU, say.
string | null
Optional property an external system identifies customers by.
string | null
Optional object holding the people inside a customer account (Contacts, say).
An event’s
user is matched to a record of this object.string | null
Optional property on the actor object that an event’s
user is matched against:
an email, say.string | null
ISO 8601 timestamp.
Two keys, on purpose
Recording usage and reading it back need different keys, and the split is deliberate:track takes a publishable key so it can be called straight from a browser at
the moment of consumption. Reading events back is not publishable. A
client-side key must never be able to enumerate a workspace’s usage.
Recording usage
Use@custral/js from your app:
event name. user is
optional.
customerRecordId, productRecordId and user each accept a Custral record id,
or a value of the module’s identifier property on that side (your own account id,
a SKU, an email).
Identifiers that match no record
If an identifier matches no record, the event is still stored, but it counts toward no record’s usage.track tells you which side missed:
customerKey / productKey. It is never
stored as a record id. To see what is waiting and under which keys:
GET /v1/usage-modules/{id}/unmatched needs usage:read. Later events with that
key start matching once a record carries it in the module’s identifier property.
Reading it back
With the server SDK, holdingusage:read:
event, actorRecordId / actorKey (who did it), and
customerKey / productKey when that side matched no record. Filter by event
to read one kind of event.
Events come back newest first, 50 to a call. That is the one list in the API
whose length is set by your own application rather than by anything a person
does in the workspace, so it always pages. A call without limit is a page, not
the history.
integer
Page size, 1–200. Defaults to 50.
integer
Rows to skip, for the next page.
Usage per record
Two reads answer the questions a usage table is usually built for, already totalled. They are the same figures the Usage by customer and Usage by product blocks show.
Both need a secret key with
usage:read and records:read. The response
names records, and usage:read on its own never reveals a record’s name.
You don’t pass a module. It is found from the record’s object: the module whose
product object (for by-customer) or customer object (for by-product) that
record belongs to. When several modules meter the object, the oldest is read,
every one is listed in modules, and moduleId picks another.
breakdown is null when no module meters the object on that side, for
example a customer record passed to by-customer.
string
Query parameter. The usage module (
umod_…) to read, when several meter the record’s object.Usage by customer
Usage by product
products lists products in use first, most used first, and never cuts them.
Products this customer did not use fill the rest, up to 25 rows, most recently
used first; moreNotUsed counts the ones left out. Each row’s weeks lines up
with weekStarts, and slippingPercent uses the same 14-day rule as
slipping above, for this customer on this product.
Names and what you can read
Counts cover every customer. The named lists (topCustomers, slipping,
neverTried.examples and products) only include records the key can read, so
a private account is counted but not named.
A record with no usable name comes back with name: "", never its id. Show
your own placeholder.
A record that doesn’t exist, or that the key can’t read, is not_found, and so
is a record that isn’t in {object}.