Predict.aiDocs
Signals

Events

Discrete, timestamped occurrences — recorded under named streams, automatically scored, and shown alongside your signals.

Signals are continuous — a value every tick. Events are discrete: things that happen. A product launch, an outage, a news headline, a policy change. Each event is a timestamped piece of text recorded under a named stream (its key), and streams work like signals do: one name, many occurrences, listed and charted together.

What makes events useful for forecasting is scoring. Every recorded event is scored automatically in the context of your workspace — its sentiment, how significant it is, how relevant to your domain, and its expected directional impact — so a stream of raw text becomes a numeric series a chart can render and an analysis can reason about.

How an event flows

  1. You record an event (or a webhook delivers one, or an ingestion mapping flags a column is_event).
  2. It's stored immediately with "status": "pending" — visible right away.
  3. Scoring runs in the background and fills in scores; the status becomes scored. Scoring is deterministic, so re-submitting the same event re-scores to the same row rather than duplicating it.

Two clocks matter, and they're stored separately:

FieldMeaning
occurred_atWhen the event actually happened (primary — this is where it plots)
timestampWhen it was recorded (always ≥ occurred_at)

Backfilling history is therefore safe: record last month's incident with occurred_at set to when it happened, and it lands in the right place on the time axis.

Record an event

curl -X POST "$API_BASE/v1/event/record" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "press_mentions",
    "text": "Featured in the Sunday retail roundup — strong coverage of the summer line.",
    "occurred_at": "2026-07-12T09:00:00Z"
  }'
{
  "data": {
    "event_id": "9f2c41d0-…",
    "stream": "press_mentions",
    "status": "pending"
  }
}

Request body

FieldMeaning
key requiredThe stream to record under. Created on first use.
text requiredThe event's content — what happened. This is what gets scored.
occurred_at optionalWhen it happened: epoch seconds, epoch milliseconds, or ISO 8601. Defaults to now.
name optionalA short display label. Defaults to the first 200 chars of text.
source optionalProvenance label ("who reported this"). Defaults to the stream key.
origin optionalOne of manual, api (default), ingestion.
value optionalAn optional numeric value attached to the event.
data_type optionalContent type hint. Defaults to "text".
raw optionalThe original payload, kept for reference.

Errors

StatusWhyExample message
400No stream"Event stream ('key') is required"
400No content"Event 'text' is required"

Fetch one event

Poll this after recording to see the scores land:

curl "$API_BASE/v1/event/$EVENT_ID" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"
{
  "data": {
    "event_id": "9f2c41d0-…",
    "key": "press_mentions",
    "name": "Featured in the Sunday retail roundup — strong coverage of the s…",
    "text": "Featured in the Sunday retail roundup — strong coverage of the summer line.",
    "source": "press_mentions",
    "origin": "api",
    "data_type": "text",
    "value": null,
    "occurred_at": 1783587600000,
    "timestamp": 1783842900000,
    "status": "scored",
    "scores": {
      "sentiment": "positive",
      "polarity": 0.6,
      "importance": 0.45,
      "relevance": 0.8,
      "impact": 0.35,
      "rank": 57
    },

  }
}

The score fields:

FieldRangeMeaning
sentimentnegative / neutral / positiveOverall tone
polarity−1 … 1Signed tone strength
importance0 … 1How significant the event is in general
relevance0 … 1How relevant it is to this workspace's domain
impact−1 … 1Expected signed effect on your targets
rank0 … 100Composite headline score (importance + relevance + magnitude of impact)

Purely numeric content (a number column flagged as an event) has nothing to interpret, so it scores neutral (rank: 0) instantly. An unknown event_id returns 404 ("Event not found").

List event streams

One row per stream, with a summary and a time-ordered points series (one point per event, ordered by occurred_at) ready to render as a sparkline:

curl "$API_BASE/v1/event/streams" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"
{
  "data": {
    "streams": [
      {
        "key": "press_mentions",
        "count": 14,
        "latest_occurred_at": 1783587600000,
        "latest_timestamp": 1783842900000,
        "latest_text": "Featured in the Sunday retail roundup — strong coverage of the summer line.",
        "latest_sentiment": "positive",
        "max_rank": 82,
        "points": [
          { "occurred_at": 1781000000000, "timestamp": 1781003600000, "rank": 41, "polarity": -0.2, "sentiment": "negative", "impact": -0.15 },

        ]
      }
    ]
  }
}

Event streams also appear directly in GET /v1/signal alongside your signals — one row per stream, tagged "type": "event" — so one call shows the whole workspace.

Delete a stream

Deletes every event recorded under the stream:

curl -X DELETE "$API_BASE/v1/event/streams/press_mentions" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"
{ "data": { "stream": "press_mentions", "deleted": 14 } }

Event streams shared into your workspace by subscription are read-only — deleting one returns 403 ("Subscribed … event streams are read-only.").

Events pair naturally with the event-style engineered features on segments: record what happened as events for context and scoring, and let release_flag / release_surprise capture when your data moved — the two views complement each other.

On this page