For the complete documentation index, see llms.txt. This page is also available as Markdown.

Usage Data

Field reference, deduplication rules, and examples for sending activity data to Harmony

A usage push tells Harmony what people actually did in an application. Where a users push reports who has access, a usage push reports who used that access — which is what turns an inventory into a license optimization tool.

This page covers the usage endpoint in full. For setup, see Bring Your Own App.

How usage differs from users

Usage pushes are additive, not snapshots. Each push adds activity records to what Harmony already has. Nothing is removed by omitting it — there is no equivalent of the users snapshot rule here.

Instead of replacement, usage relies on deduplication: every record carries an event_id that you choose, and Harmony counts each event_id exactly once no matter how many times you send it. That is what makes usage pushes safe to retry.

Send a users push before your first usage push. Activity is attributed to users Harmony already knows about. Reporting activity for someone who has never appeared in a users push means that activity is not counted.

Endpoint

POST https://external.harmony.io/custom-push/v1/usage
Authorization: Bearer <access key>
Content-Type: application/json

Request body

Field
Type
Required
Description

external_app_id

string

Yes

The App ID you registered in Harmony. Must match the value used in your users pushes for this application.

events

array

Yes

Between 1 and 100 activity records. See below.

schema_version

string

No

Defaults to "1.0". Reserved for future versions of this API.

Usage fields

Each object in the events array describes one activity observation.

Field
Type
Required
Limit
Description

event_id

string

Yes

1–255 chars

Your stable identifier for this record. This is the deduplication key — see The event ID contract below. Getting this right is the single most important part of a usage push.

event_date

string

Yes

YYYY-MM-DD

The calendar day the activity happened, in UTC. Usage is tracked per day; there is no need for a timestamp.

actor_email

string

Yes

Valid email, max 254 chars

The email address of the person who performed the activity. This is how the record is attributed to a user and, through them, to an employee.

actor_id

string

No

255 chars

The application's own identifier for that person — the same value you send as external_id in your users push. Recommended: it makes attribution reliable even if a user's email address changes.

action

string

Yes

1–255 chars

What the user did, as a short label. Becomes a named activity metric in Harmony. Keep the set of values small and stable — login, message_sent, report_generated.

metric_value

number

Yes

≥ 0, finite

How much of that action occurred. For a per-interaction record this is usually 1; for a daily total it is the count for that day.

outcome_reason

string

No

See values below

What metric_value measures. Defaults to request_count.

metadata

object

No

1 KB serialized

Any additional key/value data you want to carry along. Free-form JSON.

outcome_reason values

Value

metric_value represents

request_count

A number of actions or interactions. This is the default.

token_used

A quantity of consumed units, such as AI tokens or API credits.

cost_usd

An amount of money in US dollars.

Use this to report cost or consumption alongside plain activity counts. A single application can send several actions with different outcome_reason values — for example action: "chat_message" with request_count, and action: "chat_message" with cost_usd for the same day's spend.

The event ID contract

event_id is how Harmony knows whether two records describe the same activity or two different activities.

  • Sending the same event_id twice is always safe. The second one is ignored. Retry freely.

  • Sending the same real-world activity under a new event_id counts it twice. This is the failure mode to avoid.

Because of that, an event_id must be derived from the data, never generated fresh at send time.

There are two correct approaches. Pick the one that matches your data.

If your application has native event IDs

Some applications record every interaction individually with its own identifier — an audit log ID, an event ID, a message ID. Use it directly.

With native IDs, many records per user per day are expected and correct — one per interaction.

If you report daily totals

Most applications only expose aggregates: "Alice sent 47 messages on July 20th". Build a natural key from the values that make the record unique.

Re-running your script for July 20th produces the same key, so the record is recognized and updated rather than added again. This is what makes daily backfills and overlapping date ranges safe.

Event IDs only need to be unique within one application. You can use the same scheme across every application you push — Harmony keeps them separate.

The 90-day activity window

Harmony's activity statistics are calculated over a rolling 90-day window.

Usage records older than 90 days are accepted and stored, but they do not appear in activity charts or influence active/inactive user determination. If you are backfilling history, anything beyond 90 days will not surface in the interface.

For an initial load, pushing the last 90 days of activity gives you a complete picture immediately. Older history is optional.

Response

202 Accepted:

Field
Description

batch_id

A unique identifier for this request. Useful when contacting support about a specific push.

accepted_rows

How many activity records were accepted.

Unlike a users push, there is no snapshot_id — usage records are independent, so there is nothing to join across requests.

For error responses, see the API reference.

Examples

A minimal push

A fully populated push

Reporting both an activity count and its cost for the same day:

Note the two distinct event_id values. They describe two different measurements of the same day's work, so they must not collide.

A daily usage script

Because the event IDs are deterministic, this script is safe to re-run, safe to run twice by mistake, and safe to point at an overlapping range of dates when catching up.

Daily is the usual pattern: each morning, push yesterday's activity. Applications that expose real-time events can push more frequently.

If your script misses a day, simply include the missed dates in the next run. Deterministic event IDs make overlapping ranges harmless.

See also

  • Users data — reporting who has access

  • API reference — errors, retries, and limits

Last updated

Was this helpful?