Predict.aiDocs
Signals

Push & manage

Push values, list and inspect signals, delete, and manage display names, units, and groups.

Push a value

One call, one value:

curl -X POST "$API_BASE/v1/signal/push" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{ "key": "daily_sales", "value": 12841.5, "timestamp": "2026-07-15T00:00:00Z" }'
{ "status": "ok" }

Request body

FieldMeaning
key requiredThe signal's key. If it's new, the signal is created implicitly.
value requiredThe value — number, string, or boolean.
timestamp optionalISO 8601. Defaults to now.

Duplicate pushes for the same key and timestamp are safe — the newest value wins. Each push counts as one streaming event against the workspace's monthly allowance (Billing).

Errors

StatusWhyExample message
400Missing key or value, or empty body"Missing required fields in signal data"
400New key would exceed your plan's signal-type cap"Cannot add new signal type 'daily_sales'. Your plan allows a maximum of 25 signal types per workspace."
400Total stored values would exceed your plan's cap"Signal limit reached. Your plan allows 100000 signals per workspace."
403The key is a subscribed read-only signal"Cannot push to a … subscribed signal. Subscribed signals are read-only."

List signals

Paginated rows with pre-binned chart data per key:

curl "$API_BASE/v1/signal?page=1&per_page=25" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"
{
  "data": {
    "signals": [
      {
        "key": "daily_sales",
        "type": "signal",
        "value_types": ["continuous_numerical"],
        "signal_count": 730,
        "bins": [ { "from": "2026-06-01T00:00:00+00:00", "count": 20, "avgValue": 12100.4 },  ],
        "min_timestamp": "2024-07-15T00:00:00+00:00",
        "max_timestamp": "2026-07-14T00:00:00+00:00",
        "total_duration": 63072000,
        "display_name": "Daily sales",
        "group": "Store ops",
        "group_origin": "user",
        "unit": "$",
        "unit_origin": "user",

      }
    ],
    "event_markers": [  ],
    "pagination": {
      "total_pages": 1,
      "total_items": 12,
      "current_page": 1,
      "per_page": 25
    }
  }
}

Query parameters

ParameterMeaning
page / per_page optionalPagination. Defaults 1 and 100.
start_date / end_date optionalWindow to bin over (interpreted in the X-Timezone header's zone, default UTC). Defaults to the full data range.
number_of_bins optionalChart resolution per row. Defaults to 36.
group optionalOnly signals in one group; pagination reflects the filtered set.
sort_by optionalrelevance (default), records, recency, name, published, unpublished.
sort_order optionalasc or desc (default).
published_filter optionalall (default), published, unpublished.

Rows arrive annotated with display_name, group, and unit so you don't need follow-up calls to render a signal table.

Workspace overview

/list returns one row per key. For a chart that stays readable at any scale, /overview resolves a hierarchical view — per-signal series for small workspaces, group envelopes (median + band) when there are many:

curl "$API_BASE/v1/signal/overview?number_of_bins=240" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"
{
  "data": {
    "mode": "groups",
    "path": [],
    "groups": [ { "id": "sales", "label": "Sales", "count": 14, "bins": [  ] },  ],
    "signals": [],
    "pinned": [],
    "catalog": [ { "key": "daily_sales", "group": "sales" },  ],
    "total_signals": 220,
    "member_total": 220,
    "events": [  ]
  }
}

Query parameters

ParameterMeaning
group optionalDrill into one group — its members come back as individual series.
pins optionalComma-separated keys to always show as individual series.
start_date / end_date optionalWindow to bin over, as on /list.
number_of_bins optionalChart resolution. Defaults to 240.

Check for data

A cheap probe — does this workspace have any signal data at all?

curl "$API_BASE/v1/signal/has-data" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"
{
  "data": {
    "has_data": true,
    "signal_count": 48210,
    "subscribed_signals_count": 0
  }
}

Delete one signal

Deletes every stored value for a key:

curl -X DELETE "$API_BASE/v1/signal?signal_type=daily_sales" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"
{ "status": "deleted" }

Query parameters

ParameterMeaning
signal_type requiredThe key to delete.
force optionalIf the signal is published for sharing, the first call returns 409 with a summary of what deleting would delist; confirm by re-sending with force=true.

Errors

StatusWhyExample message
400Missing signal_type"Signal type is missing"
403The key is a subscribed read-only signal"Cannot delete a … subscribed signal. Cancel the subscription … instead."
409The signal is published for sharing; re-send with force=true"This signal is published … with 2 active subscribers. …"
404Nothing stored under that key"No signals found to delete"

Delete in bulk

One batch, many keys:

curl -X POST "$API_BASE/v1/signal/delete" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{ "keys": ["daily_sales", "web_traffic"], "force": false }'
{
  "data": {
    "deleted": ["daily_sales", "web_traffic"],
    "deleted_event_streams": [],
    "skipped_marketplace": []
  }
}

Request body

FieldMeaning
keys requiredThe signal keys to delete.
force optionalConfirm deletion of keys that are published for sharing. Defaults to false.

Subscribed read-only keys are never deleted — they're skipped and reported in skipped_marketplace. If any key in the batch is published for sharing and force isn't set, the whole batch is rejected with 409 and a listing summary; re-send with "force": true to confirm. A batch of only read-only keys returns 403. Group assignments and display names of deleted keys are cleaned up automatically.

Display names

Set (or clear, with an empty name) the friendly label for one key:

curl -X POST "$API_BASE/v1/signal/display-name" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{ "key": "o", "display_name": "Open" }'
{ "data": { "key": "o", "display_name": "Open" } }
FieldMeaning
key requiredThe signal key to label.
display_name optionalThe friendly label. An empty string clears it.

Fetch the whole map in one call:

curl "$API_BASE/v1/signal/display-names" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"
{ "data": { "o": "Open", "h": "High", "daily_sales": "Daily sales" } }

A missing key returns 400 ("key is required").

Units

Assign a measurement unit to one or more keys; omit or empty unit to clear (the key reverts to the automatically inferred unit, or none):

curl -X POST "$API_BASE/v1/signal/units/assign" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{ "keys": ["spot_price", "day_ahead_price"], "unit": "$/MWh" }'
{ "data": { "updated": 2, "unit": "$/MWh" } }
FieldMeaning
keys requiredThe signal keys to assign the unit to.
unit optionalThe unit string, e.g. "$/MWh". Omit or send empty to clear — the key reverts to the automatically inferred unit, or none.

GET /v1/signal/units returns every persisted unit:

{
  "data": {
    "units": {
      "spot_price": { "unit": "$/MWh", "origin": "user" },
      "load_mw": { "unit": "MW", "origin": "llm" }
    }
  }
}

Groups

Groups organize large workspaces. GET /v1/signal/groups returns the resolved grouping for every key plus your explicit overrides:

curl "$API_BASE/v1/signal/groups" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"
{
  "data": {
    "groups": [
      { "name": "Store ops", "count": 14, "origins": { "user": 2, "inferred": 12 } },

    ],
    "assignments": {
      "daily_sales": { "group": "Store ops", "origin": "user" }
    }
  }
}

Assign keys to a group (your assignment always wins over automatic grouping):

curl -X POST "$API_BASE/v1/signal/groups/assign" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{ "keys": ["daily_sales", "foot_traffic"], "group": "Store ops" }'
{ "data": { "assigned": 2, "group": "Store ops" } }
FieldMeaning
keys requiredThe signal keys to assign.
group requiredThe group name. Created on first use.

Remove explicit assignments — the keys revert to automatic grouping:

curl -X POST "$API_BASE/v1/signal/groups/unassign" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{ "keys": ["foot_traffic"] }'
{ "data": { "unassigned": 1 } }

All three write endpoints return 400 ("keys is required") when keys is missing or empty.

On this page