Skip to main content

Events, Storylines and Arcs

LevelWhat it isExample
EventOne thing that happened, written up from the posts that reported itUS Treasury sanctions A7 Network over more than $17 billion in transfers
StorylineThe events of one development, threaded over daysUS Treasury and FinCEN target A7 network over sanctions evasion (2 events)
ArcStorylines that belong to one larger movementStrategy 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.

FieldMeaning
idThe event id. Pass it back in eventIds
eventClassmarket: a development reported across posts. asset: posts about one asset, nothing wider. call: accounts taking positions, see below
alertTitle, summaryA one-line title and a short summary. Either can be null
implicationLikely direction for the assets it names: bullish, bearish, mixed, unclear. Can be null
eventTypesecurity, listing, regulatory, macro, protocol, company, marketFlow, price, social or other. Can be null
primaryEntitiesWhat it is about. Can be empty: a shipping attack names no asset
relatedEntitiesNamed alongside
alertActionalert: judged impactful. monitor: worth watching
originCountDistinct 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
impactsMeasured price reactions. Empty on most events. See below
analyzedAtWhen it was written up. from, to and the order use this
firstSeenAtThe earliest post behind it we saw, not when the news broke. Can be null
storylineIdIts storyline. Null on a call event, and on the few not threaded
citedSourcesThe posts behind it, up to 10. See below
positionsNull except on a call event
noveltynew: 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​

sourcehandlesourceRecordIdlink
twitterThe X accountThe post's idThe post on X
telegramThe sender's Telegram name. Not an X handleA reference to a group of messagesnull

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
}
]
}
FieldMeaning
priceChange1dReturn over the 24 hours from the first post: 0.0157 is +1.57%. Null until measured
movedFirsttrue: the price moved unusually, the same way, in the hour before the first post. Null until measured
marketWidetrue: BTC moved unusually at the same time. Null until measured
finalfalse 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​

ParameterValuesDefaultNotes
qtext, up to 500 charactersSearch by topic. See Search by Topic
fromUnix secondsrequired unless eventIds or qAgainst analyzedAt. Not with eventIds
toUnix secondsnow
entityIdsup to 30 entity ids, a listEvents naming any of them, as subject or alongside
eventClassmarket, asset, callall
eventTypeone eventTypeallspam is a 400
implicationbullish, bearish, mixed, unclearall
assetClasscrypto, equitybothEvents naming no asset, like a macro story, come through either way
noveltynew, updateboth
hasStorylinetrue, falseeitherIn a storyline, or in none
arcIdone arc idEvents in that arc's storylines. A retired arc has no members, so none
notabletrue, falsetrue drops events a storyline marked as not material. false is no filter
alertActionalert, monitor, a listboth
sortlatest, relevantlatestSee below
eventIdsup to 30 event ids, a listCombines only with alertAction, order and sort=latest
orderdesc, ascdesc
limit1 to 3010Ignored with eventIds
cursornextCursor 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, arcId and order=asc are refused with it.
  • assetClass, alertAction, hasStoryline, notable and entityIds still filter. entityIds must 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. servedFrom is null.

Errors​

The common errors, plus:

AnswerWhenDo
400, Unknown id: …arcId is an arc we do not holdTake it from an arc list
400, eventIds cannot be combined with …eventIds with a range or filterDrop one or the other
400, sort=relevant cannot be combined with …sort=relevant with what it refusesDrop those, or use sort=latest
400, sort=relevant filters by asset ids only…A person, project or organisation in entityIdsUse sort=latest
400, This plan answers from … onwards.Also: a sort=relevant cursor that oldStart 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.

FieldMeaning
title, summaryWhat the thread is about, and an account of it so far
statusopen while events that add something arrive. dormant after three quiet days, until one does
entitiesEverything the thread names. Can be empty
startedAt, lastEventAtFirst 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
lastMaterialAtWhen 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
arcIdIts active arc. Null on most threads, and once the arc retires
eventsIts 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​

relationThe event…
originstarted the thread
updatemoved it forward
confirmationconfirmed an earlier claim
contradictiondisputed an earlier claim
mitigationsoftened an earlier development
consequencefollowed from it
reactionis someone responding to it
contextadded background

Parameters​

ParameterValuesDefaultNotes
qtext, up to 500 charactersSearch by topic. See Search by Topic
fromUnix secondsrequired unless storylineIds or qThreads with an event since then. With q: rewritten since then
toUnix secondsnow
storylineIdsup to 30 storyline ids, a liststatus is ignored, other filters apply
entityIdsup to 30 entity ids, a listThreads naming any of them
statusopen, dormant, anyopen; every status with qany reads both. A search reads both unless you send one
relationrelations, a listThreads with a listed event of this relation. Does not filter events
orderdesc, ascdesc
limit1 to 3010
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 sendYou getOrder
Nothing, status or arcIdsActive or retired arcsLast updated
qArcs matching a topic, active or retired by statusBest match
assetClass, entityIds or sortActive arcs in a market or about assets: the list the Elfa app calls narratives. Macro arcs, in neither market, come after the market's ownNewest 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.

FieldMeaning
name, summaryWhat the movement is. summary is null on some older retired arcs
statusactive or retired. A retired arc lists the storylines it held when it retired
storylineIdsIts storylines, in no order. Read lastEventAt on each for recency
updatedAtWhen its name, summary or membership last changed, or a member's title or summary

Parameters​

ParameterValuesDefaultNotes
qtext, up to 500 charactersSearch by topic. See Search by Topic
arcIdsup to 30 arc ids, a listActive or retired. status is ignored
statusactive, retiredactive
assetClasscrypto, equitybothArcs with at least 15% of their events naming an asset of this class
entityIdsup to 30 token or equity ids, a listArcs about any of them
sortlatest, storylines, eventslatest: newest event first. The others: most first
orderdesc, ascdescBy updatedAt
limit1 to 3010
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.

AnswerWhenDo
400, … reads active narratives, newest first; it cannot be combined with …assetClass, entityIds or sort with arcIds, status=retired or order=ascDrop one side
400, Narratives filter by asset ids only.A person, project or organisation in entityIdsPass token or equity ids
Other 400sSee the common errors

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.

EndpointTakes with qRefuses with q
/v3/eventsfrom, to, entityIds, eventType, alertAction, hasStorylineeventIds, eventClass, implication, novelty, notable, arcId, assetClass, sort=relevant
/v3/events/storylinesfrom, to, entityIds, statusstorylineIds, relation
/v3/events/arcsstatusarcIds, assetClass, entityIds, sort
  • A word, a ticker or a phrase: hack, NVDA and solana outage all work on events and storylines. For everything about one asset, resolve it with /v3/entities and pass entityIds, alone or with q to narrow it to a topic.
  • from is optional: it defaults to the start of your history, and servedFrom says where it started.
  • Storylines of every status. A storyline search reads open and dormant threads unless you send status: most threads on a topic have gone quiet. Send status=open for only the ones still developing. Between two matches of similar relevance, the more recently started thread ranks first. from and to bound 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 limit with more to follow.
  • Every page ranks as of the first, so paging never repeats or skips. order=asc is refused.
AnswerWhenDo
400 on query.q, q ranks by relevance; it cannot be combined with …q with a parameter it refusesDrop those
400, q must not be empty or q must be 500 characters or lessq blank or too longShorten it
400, A search serves its first 100 matches only.A cursor past the 100th matchNarrow the search instead
503, Search is unavailable right now. Retry, or drop q.Search is downRetry after a few seconds, or drop q