Skip to content

Send your own scores

A streaming input is a per-user value that arrives already worked out, such as a churn score, an engagement band or a count over a time window. Your server sends a batch of them for one site, and EdgeKit stores the latest value for each user on that site. A profile field reads it, and so does a Paywall rule, as streaming.<pipeline>.<field>. Both read it at Computed trust.

A pipeline names one stream of values. Each pipeline has a source: EdgeKit’s own analytics, or your organization. This page covers pipelines whose source is your organization.

EdgeKit staff declare pipelines. Ask EdgeKit to declare yours with your organization as its source, and give each field a name and a type: string, integer, number or boolean. Pipeline and field names are lowercase letters, digits and underscores, starting with a letter. user_id, site_id and window_end are on every row already and cannot be declared.

The declaration is part of your draft, so it reaches requests after the next deploy, and that deploy rebuilds every profile. The Streaming tab of Identity › Audience › Profile shows each declared pipeline, its source and its fields, read-only.

  1. Open the site from Delivery › Delivery › Sites and go to API keys.
  2. Select Can send streaming scores (streaming:write) and issue the key. See Issue and revoke API keys.

The values are written for the key’s site. To send values for two sites, issue a key on each. Keep the key on your server; this route is never called from a page.

POST /v1/streaming/<pipeline> on your tenant host takes up to 1000 rows. Each row carries:

  • user_id: the user’s EdgeKit user id.
  • window_end: the end of the window the values describe, as an ISO-8601 UTC timestamp or epoch milliseconds.
  • The pipeline’s declared fields. A field you leave out keeps its stored value, null clears it, and an undeclared field is ignored.

A site_id in a row is ignored: the site is always the key’s.

Terminal window
curl -X POST https://your-tenant-host/v1/streaming/churn_model \
-H 'Authorization: Bearer ek_your_key' \
-H 'Content-Type: application/json' \
-d '{"rows": [{"user_id": "01928c4e-7d3a-7b2e-9f10-3c5d2a1b0e9f", "window_end": "2026-10-17T00:00:00Z", "churn": 0.42}]}'
const response = await fetch(
'https://your-tenant-host/v1/streaming/churn_model',
{
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.EDGEKIT_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
rows: [
{
user_id: '01928c4e-7d3a-7b2e-9f10-3c5d2a1b0e9f',
window_end: '2026-10-17T00:00:00Z',
churn: 0.42,
},
],
}),
},
);
const { received, rejected } = await response.json();

200 means the batch was read. received counts the rows that landed, and rejected counts the rest by reason. The counts add up to the batch size.

Reason The row
missing_user_id has no user_id.
missing_window_end has no window_end, or one that is not a timestamp.
unknown_site was sent with a key whose site is not in your newest deployment.
unknown_user names no user in your organization.
erased names an erased user. Values for an erased user are never stored.
stale wrote no field: each one it carries is older than the stored value, or none is declared.
type_mismatch carries a value of the wrong type for its field.

Accept a reason not in this list: new ones can be added.

The request is safe to retry. A row sent again with the same window_end writes the same values again, and a row older than the stored values is stale, never written over them.

Each landed row rebuilds that user’s profile on that site. The Streaming tab’s Activity shows when each field last received a value, and refused deliveries counted by reason.

Status Code When
400 bad_request The body is not valid JSON.
401 unauthorized The key is missing, unknown, revoked or expired.
403 forbidden The key does not hold streaming:write, or the pipeline’s source is not your organization.
404 not_found No pipeline of that name is in your newest deployment.
413 payload_too_large The batch has more than 1000 rows.
422 unprocessable_entity The body is not { "rows": [...] }.

See the operation reference.

  • In a profile field, streaming.<pipeline>.<field> is listed on Available data. See Define a profile field.
  • In a Paywall rule, a condition can read streaming.<pipeline>.<field> directly. The value is the last one written. For a signed-in user with no value yet, the condition that reads it does not hold, and nothing errors.