Events, Storylines and Arcs
| Level | What it is | Example |
|---|---|---|
| Event | One thing that happened, written up from the posts that reported it | US Treasury sanctions A7 Network over more than $17 billion in transfers |
| Storyline | The events of one development, threaded over days | US Treasury and FinCEN target A7 network over sanctions evasion (2 events) |
| Arc | Storylines that belong to one larger movement | Strategy Bitcoin treasury expansion and capital-raising episode (2 storylines) |
event ── storylineId ──▶ storyline ── arcId ──▶ arc
event ◀── events[].eventId ── storyline ◀── storylineIds ── arc
Fetch whatever you hold ids for with eventIds, storylineIds or arcIds,
up to 30 at a time, or search all three by topic with q.
Not returned: post text, a sentiment score or a price, and noise. Only events
judged worth showing are served (alert or monitor), never spam, and never
an event its storyline marks as a duplicate.
Events
GET /v3/events: events in a time range, newest first. Or the last 24 hours ranked by relevance
(see below), events matching a topic, or up to 30 by id.
{
"events": [
{
"id": "df5e5c1a-afe8-49ed-addc-26a051c4bf9b",
"eventClass": "market",
"alertTitle": "US Treasury sanctions A7 Network over more than $17 billion in transfers, including A7A5",
"summary": "The US Treasury sanctioned Russia-linked A7 Network, citing more than $17 billion in transfers and alleged links to sanctions evasion and illicit activity. FinCEN also proposed restricting transfers involving the network’s correspondent accounts; the reports identify A7A5 as part of the network.",
"implication": "bearish",
"eventType": "regulatory",
"primaryEntities": [
{
"id": "ce405903-8e5b-49fd-863d-833ac86c3e19",
"symbol": "A7A5",
"name": "A7A5",
"entityType": "token"
}
],
"relatedEntities": [],
"alertAction": "alert",
"originCount": 3,
"impacts": [],
"analyzedAt": 1790927766,
"firstSeenAt": 1790912074,
"storylineId": "372aeadc-88d5-4cce-9bbc-3f9cab047758",
"citedSources": [
{
"source": "twitter",
"sourceRecordId": "2105863989955908057",
"handle": "WuBlockchain",
"link": "https://x.com/WuBlockchain/status/2105863989955908057"
},
{
"source": "telegram",
"sourceRecordId": "telegram_group:4d08f1ea0b642ed6cc86c63ea98467d3",
"handle": "wublockchainenglish",
"link": null
}
],
"positions": null,
"novelty": "new"
}
],
"nextCursor": "TUHFseJr.MjAyNi0xMC0wMiAwNzo1NjowNi44NDM5NDkrMDB8ZGY1ZTVjMWEtYWZlOC00OWVkLWFkZGMtMjZhMDUxYzRiZjli",
"hasMore": true,
"servedFrom": 1790672305
}
GET /v3/events?from=1790672305&alertAction=alert, trimmed to one event and
2 of its 3 cited posts.
| Field | Meaning |
|---|---|
id | The event id. Pass it back in eventIds |
eventClass | market: a development reported across posts. asset: posts about one asset, nothing wider. call: accounts taking positions, see below |
alertTitle, summary | A one-line title and a short summary. Either can be null |
implication | Likely direction for the assets it names: bullish, bearish, mixed, unclear. Can be null |
eventType | security, listing, regulatory, macro, protocol, company, marketFlow, price, social or other. Can be null |
primaryEntities | What it is about. Can be empty: a shipping attack names no asset |
relatedEntities | Named alongside |
alertAction | alert: judged impactful. monitor: worth watching |
originCount | Distinct accounts behind the event: the cited posts' accounts, plus, on a market event, every account whose post joined the story since and passed our source gate. A market event's count is read live, so it grows after analyzedAt; asset and call events keep their cited accounts |
impacts | Measured price reactions. Empty on most events. See below |
analyzedAt | When it was written up. from, to and the order use this |
firstSeenAt | The earliest post behind it we saw, not when the news broke. Can be null |
storylineId | Its storyline. Null on a call event, and on the few not threaded |
citedSources | The posts behind it, up to 10. See below |
positions | Null except on a call event |
novelty | new: the story's first reading. update: a later one. Send novelty=new to see each story once |
Each entity has id, symbol (tokens and equities only), name and
entityType: token, equity, project, person or organisation. Assets
are named by their family: wrapped bitcoin is
BTC.
Cited Sources
source | handle | sourceRecordId | link |
|---|---|---|---|
twitter | The X account | The post's id | The post on X |
telegram | The sender's Telegram name. Not an X handle | A reference to a group of messages | null |
source is an empty string when we cannot tell. No field holds post text.
The first entries are the posts the write-up cited, in its order. On a
market event, later posts from other accounts that passed our source gate
(close to the story, enough text of the author's own, from an account in good
standing) come after them, one per account, newest story-joiners included on
every read. The list stops at 10, so originCount can be larger than its
length.
asset and call events list only the cited posts. A call is what traders
said at one moment, so a later post on the asset is a different trade; an asset
event gathers posts by asset, so a later post on it is rarely about the same
story.
Impacts
One entry per asset in primaryEntities we could price. From the September
jobs report event:
{
"id": "ca1bd2f8-a504-4c12-bd10-ae62bef34194",
"alertTitle": "U.S. September jobs report is a near-term volatility catalyst for BTC and ETH",
"firstSeenAt": 1790906717,
"impacts": [
{
"entityId": "b23e0b47-deec-4161-b49c-7e2652f07fe6",
"symbol": "BTC",
"priceChange1d": 0.015719866,
"movedFirst": false,
"marketWide": true,
"final": false
},
{
"entityId": "0fdfbd36-2ec0-4e72-a074-50c6df7e3e20",
"symbol": "ETH",
"priceChange1d": 0.009786248,
"movedFirst": false,
"marketWide": false,
"final": false
}
]
}
| Field | Meaning |
|---|---|
priceChange1d | Return over the 24 hours from the first post: 0.0157 is +1.57%. Null until measured |
movedFirst | true: the price moved unusually, the same way, in the hour before the first post. Null until measured |
marketWide | true: BTC moved unusually at the same time. Null until measured |
final | false until measuring ends, usually a day after the first post, at most about eight. Values can change until then |
Either flag true means the move probably has another cause; both false
does not prove the event caused it. Above, BTC moved with the market.
Call Events
Several accounts taking positions on the same asset, reported as one event:
{
"id": "55e6b539-5e1b-4461-9753-1f53ee21c888",
"eventClass": "call",
"alertTitle": "Bitcoin shorts target $79K and build positions between $86.5K and $89.5K",
"implication": "bearish",
"primaryEntities": [
{ "id": "b23e0b47-deec-4161-b49c-7e2652f07fe6", "symbol": "BTC", "name": "Bitcoin", "entityType": "token" }
],
"originCount": 4,
"impacts": [],
"analyzedAt": 1790930514,
"firstSeenAt": 1790807955,
"storylineId": null,
"positions": { "long": 0, "short": 9, "side": "short" }
}
positions counts posts, not accounts. side is the larger side, mixed on
a tie, null when both are 0, and implication follows it. Each account's own positions are on
Calls.
Parameters
| Parameter | Values | Default | Notes |
|---|---|---|---|
q | text, up to 500 characters | Search by topic. See Search by Topic | |
from | Unix seconds | required unless eventIds or q | Against analyzedAt. Not with eventIds |
to | Unix seconds | now | |
entityIds | up to 30 entity ids, a list | Events naming any of them, as subject or alongside | |
eventClass | market, asset, call | all | |
eventType | one eventType | all | spam is a 400 |
implication | bullish, bearish, mixed, unclear | all | |
assetClass | crypto, equity | both | Events naming no asset, like a macro story, come through either way |
novelty | new, update | both | |
hasStoryline | true, false | either | In a storyline, or in none |
arcId | one arc id | Events in that arc's storylines. A retired arc has no members, so none | |
notable | true, false | true drops events a storyline marked as not material. false is no filter | |
alertAction | alert, monitor, a list | both | |
sort | latest, relevant | latest | See below |
eventIds | up to 30 event ids, a list | Combines only with alertAction, order and sort=latest | |
order | desc, asc | desc | |
limit | 1 to 30 | 10 | Ignored with eventIds |
cursor | nextCursor from the same query |
Ranked by Relevance
sort=relevant ranks the last 24 hours by how newsworthy each event is, the
order the Elfa app's feed shows.
GET /v3/events?sort=relevant&assetClass=crypto&limit=10
- No range.
from,to,eventIds,eventClass,eventType,implication,novelty,arcIdandorder=ascare refused with it. assetClass,alertAction,hasStoryline,notableandentityIdsstill filter.entityIdsmust be tokens or equities.- Every page is ranked as of the first, so paging never repeats or skips.
Drop the cursor for a fresh ranking.
servedFromisnull.
Errors
The common errors, plus:
| Answer | When | Do |
|---|---|---|
400, Unknown id: … | arcId is an arc we do not hold | Take it from an arc list |
400, eventIds cannot be combined with … | eventIds with a range or filter | Drop one or the other |
400, sort=relevant cannot be combined with … | sort=relevant with what it refuses | Drop those, or use sort=latest |
400, sort=relevant filters by asset ids only… | A person, project or organisation in entityIds | Use sort=latest |
400, This plan answers from … onwards. | Also: a sort=relevant cursor that old | Start again without the cursor |
For errors with q, see Search by Topic.
Storylines
GET /v3/events/storylines: storylines whose latest event falls in the time range, most recently active first. Each
lists its events by id, oldest first: fetch them with
eventIds.
{
"storylines": [
{
"id": "372aeadc-88d5-4cce-9bbc-3f9cab047758",
"title": "US Treasury and FinCEN target A7 network over sanctions evasion and $17 billion in transfers",
"summary": "US authorities targeted the Russia-linked A7 network, citing more than $17 billion in transfers and alleged sanctions evasion. FinCEN proposed restricting transfers involving the network’s correspondent accounts; reports identify A7A5 as part of the network.",
"status": "open",
"entities": [
{
"id": "ce405903-8e5b-49fd-863d-833ac86c3e19",
"symbol": "A7A5",
"name": "A7A5",
"entityType": "token"
}
],
"startedAt": 1790893867,
"lastEventAt": 1790927766,
"lastMaterialAt": 1790927766,
"arcId": null,
"events": [
{
"eventId": "5576024c-0bbb-4199-b351-3ed499ad98c4",
"relation": "origin",
"material": true,
"occurredAt": 1790893867
},
{
"eventId": "df5e5c1a-afe8-49ed-addc-26a051c4bf9b",
"relation": "update",
"material": true,
"occurredAt": 1790927766
}
]
}
],
"nextCursor": null,
"hasMore": false,
"servedFrom": null
}
GET /v3/events/storylines?storylineIds=372aeadc-88d5-4cce-9bbc-3f9cab047758.
Its second event is the sanctions event above.
| Field | Meaning |
|---|---|
title, summary | What the thread is about, and an account of it so far |
status | open while events that add something arrive. dormant after three quiet days, until one does |
entities | Everything the thread names. Can be empty |
startedAt, lastEventAt | First and latest event. A list's from, to and order use lastEventAt. A search bounds from and to by when the title and summary were last rewritten instead |
lastMaterialAt | When an event last moved the thread. A reaction or context does not. Prices and levels in title and summary are as of this moment or shortly after, not now: an older thread can say "near $65,000" while the asset trades well above. Compare them with the price at lastMaterialAt |
arcId | Its active arc. Null on most threads, and once the arc retires |
events | Its events your plan can fetch, oldest first: eventId, relation, material (false: added nothing new), and occurredAt, the event's analyzedAt |
Duplicates and events older than your history are not listed, so a thread can list fewer events than it has had.
Relations
relation | The event… |
|---|---|
origin | started the thread |
update | moved it forward |
confirmation | confirmed an earlier claim |
contradiction | disputed an earlier claim |
mitigation | softened an earlier development |
consequence | followed from it |
reaction | is someone responding to it |
context | added background |
Parameters
| Parameter | Values | Default | Notes |
|---|---|---|---|
q | text, up to 500 characters | Search by topic. See Search by Topic | |
from | Unix seconds | required unless storylineIds or q | Threads with an event since then. With q: rewritten since then |
to | Unix seconds | now | |
storylineIds | up to 30 storyline ids, a list | status is ignored, other filters apply | |
entityIds | up to 30 entity ids, a list | Threads naming any of them | |
status | open, dormant, any | open; every status with q | any reads both. A search reads both unless you send one |
relation | relations, a list | Threads with a listed event of this relation. Does not filter events | |
order | desc, asc | desc | |
limit | 1 to 30 | 10 | |
cursor |
duplicate is not a relation you can send: restatements are not served.
Arcs
GET /v3/events/arcs: arcs, each with a summary and its storylines by id: fetch those with
storylineIds. Two ways to list them:
| You send | You get | Order |
|---|---|---|
Nothing, status or arcIds | Active or retired arcs | Last updated |
q | Arcs matching a topic, active or retired by status | Best match |
assetClass, entityIds or sort | Active arcs in a market or about assets: the list the Elfa app calls narratives. Macro arcs, in neither market, come after the market's own | Newest event, most storylines or most events |
{
"arcs": [
{
"id": "f61969e2-6a23-4846-8f64-846650ac96f1",
"name": "Strategy Bitcoin treasury expansion and capital-raising episode",
"summary": "Strategy says it has no fixed Bitcoin holdings target and plans to keep buying through equity and credit products. A reported purchase of about 1,665 BTC brought its holdings to 847,666 BTC.",
"status": "active",
"storylineIds": [
"2c58c41d-d3bc-4ec6-a1ea-d7c1586af7b8",
"7f10f31e-875c-4b52-a21b-7f44e49fd8b4"
],
"updatedAt": 1790924532
}
],
"nextCursor": "e9t9jB7g.MjAyNi0xMC0wMiAwNTowMjoxMS42MjExMDMrMDB8NzIwOGQyMGUtZTAyNi00ZjE0LWE4ZTEtY2FhZWQ3OTI4MTA0",
"hasMore": true
}
GET /v3/events/arcs, trimmed to one arc. Arcs take no time range, so they
carry no servedFrom.
| Field | Meaning |
|---|---|
name, summary | What the movement is. summary is null on some older retired arcs |
status | active or retired. A retired arc lists the storylines it held when it retired |
storylineIds | Its storylines, in no order. Read lastEventAt on each for recency |
updatedAt | When its name, summary or membership last changed, or a member's title or summary |
Parameters
| Parameter | Values | Default | Notes |
|---|---|---|---|
q | text, up to 500 characters | Search by topic. See Search by Topic | |
arcIds | up to 30 arc ids, a list | Active or retired. status is ignored | |
status | active, retired | active | |
assetClass | crypto, equity | both | Arcs with at least 15% of their events naming an asset of this class |
entityIds | up to 30 token or equity ids, a list | Arcs about any of them | |
sort | latest, storylines, events | latest: newest event first. The others: most first | |
order | desc, asc | desc | By updatedAt |
limit | 1 to 30 | 10 | |
cursor |
Arcs last updated before your history are left out.
With assetClass, entityIds or sort, it is arcs whose newest event is
before it instead.
| Answer | When | Do |
|---|---|---|
400, … reads active narratives, newest first; it cannot be combined with … | assetClass, entityIds or sort with arcIds, status=retired or order=asc | Drop one side |
400, Narratives filter by asset ids only. | A person, project or organisation in entityIds | Pass token or equity ids |
Other 400s | See the common errors |
Search by Topic
q searches events, storylines and arcs by what they are about, best match
first, in the same response shape. Events and storylines blend meaning with
case-insensitive word matching, and related English word forms can match
(hack, hacks). Arcs match by meaning only.
GET /v3/events?q=stablecoin%20regulation%20in%20the%20US&from=<now-30d>
1. Fed proposes stricter capital, redemption and reserve rules for stablecoin…
2. Federal Reserve proposes GENIUS Act framework for payment stablecoin…
3. CFTC proposes a first federal regulatory framework for U.S. crypto markets
GET /v3/events/arcs?q=bitcoin%20treasury%20companies
1. Strive’s Bitcoin treasury accumulation
2. Strategy’s Bitcoin accumulation
Read on 7 October 2026.
| Endpoint | Takes with q | Refuses with q |
|---|---|---|
/v3/events | from, to, entityIds, eventType, alertAction, hasStoryline | eventIds, eventClass, implication, novelty, notable, arcId, assetClass, sort=relevant |
/v3/events/storylines | from, to, entityIds, status | storylineIds, relation |
/v3/events/arcs | status | arcIds, assetClass, entityIds, sort |
- A word, a ticker or a phrase:
hack,NVDAandsolana outageall work on events and storylines. For everything about one asset, resolve it with/v3/entitiesand passentityIds, alone or withqto narrow it to a topic. fromis optional: it defaults to the start of your history, andservedFromsays where it started.- Storylines of every status. A storyline search reads
openanddormantthreads unless you sendstatus: most threads on a topic have gone quiet. Sendstatus=openfor only the ones still developing. Between two matches of similar relevance, the more recently started thread ranks first.fromandtobound when a thread's title and summary were last rewritten, so a thread that only drew restatements since an old update stays out. - At most 100 matches, and only good ones. A query nothing matches well
returns an empty list. A page can hold fewer than
limitwith more to follow. - Every page ranks as of the first, so paging never repeats or skips.
order=ascis refused.
| Answer | When | Do |
|---|---|---|
400 on query.q, q ranks by relevance; it cannot be combined with … | q with a parameter it refuses | Drop those |
400, q must not be empty or q must be 500 characters or less | q blank or too long | Shorten it |
400, A search serves its first 100 matches only. | A cursor past the 100th match | Narrow the search instead |
503, Search is unavailable right now. Retry, or drop q. | Search is down | Retry after a few seconds, or drop q |