Workflows
Recipes that chain v3 endpoints. Send each path to https://api.elfa.ai
with your x-elfa-api-key, as in the Quickstart.
<now> and <now - 1d> are Unix seconds.
One Asset at a Glance
What is happening to SOL, and how are accounts positioned?
1. GET /v3/entities?q=sol&entityType=token&limit=1
-> entities[0].id. Check its name first: see Choosing a Match
2. GET /v3/events?entityIds=<id>&from=<now - 1d>&alertAction=alert
-> the flagged events of the last day
3. GET /v3/events/storylines?entityIds=<id>&from=<now - 7d>
-> open storylines naming SOL, active in the last week, with summaries
4. GET /v3/calls/positioning?entityId=<id>
-> openLong, openShort right now
5. GET /v3/calls/episodes?entityIds=<id>&status=open&from=<now>&limit=30
-> who holds those positions, newest opened first
To cover Solana the project too, resolve both with
q=solana&entityType=token,project and pass both ids to steps 2 and 3.
Daily Market Brief
What mattered today, where is attention, and which way does the crowd lean?
1. GET /v3/events?alertAction=alert&novelty=new&from=<now - 1d>&limit=30
-> the flagged new stories of the last day. A story can still come
back as a later event marked new: keep the first per storylineId.
Page with nextCursor while hasMore is true
2. GET /v3/events/arcs
-> the larger movements. Their storylines:
GET /v3/events/storylines?storylineIds=<up to 30 ids>
3. GET /v3/market/crypto/mindshare?period=24h&limit=20
GET /v3/market/equity/mindshare?period=24h&limit=20
-> the loudest assets of the day, and which are hot right now
4. GET /v3/market/crypto/call-book?from=<now - 1h>&limit=1
GET /v3/market/equity/call-book?from=<now - 1h>&limit=1
-> the newest row of each book, usually the live tick for the
current hour: longShare, crowdingPercentile, pulse24
In step 4, report crowdingPercentile, not longShare: the crowd leans long
most days, and the percentile tells an unusual day apart.
Poll for New Events
To be told about new events rather than polling, let Auto watch for them: an
events condition takes the same filters and fires on each new
event that matches. See Alerts with Auto. To poll
yourself:
import time
last_seen = int(time.time()) - 3600 # start one hour back, in seconds
seen_ids = set()
while True:
params = {"from": last_seen - 300, "order": "asc", "limit": 30}
while True:
# The Quickstart helper. It raises on any error: on
# ERR_RATE_LIMIT_EXCEEDED, sleep and retry.
page = elfa("/v3/events", **params)
for event in page["events"]:
if event["id"] in seen_ids:
continue # overlap from the last poll
seen_ids.add(event["id"])
last_seen = max(last_seen, event["analyzedAt"])
process(event) # your code
if not page["hasMore"]:
break
params["cursor"] = page["nextCursor"] # every other param unchanged
time.sleep(60)
# seen_ids only needs ids from the last few minutes. Prune it in a
# long-running process.
fromreaches five minutes behind the newest event seen, so late arrivals are caught.seen_idsdrops the repeats.order=ascsolast_seenonly moves forward.- One alert per story: keep the
storylineIdof each event you process, and skip an event whosestorylineIdyou already hold.novelty=newalone is not enough: most later readings of a story still saynew.storylineIdis null on a call event and on the few not threaded; process those each time. - A cursor belongs to its query: keep every parameter while paging, and start each poll without one.
Follow a Storyline
An event mentions a development. How has it moved since?
1. GET /v3/events?entityIds=<id>&from=<now - 1d>
-> an event with storylineId set
2. GET /v3/events/storylines?storylineIds=<storylineId>
-> title, summary, status, lastMaterialAt, and every event id in the
thread with its relation
3. GET /v3/events?eventIds=<up to 30 event ids from step 2>
-> the events themselves. Pick the ids whose relation is update,
contradiction or consequence to skip background and reactions
4. If arcId is not null:
GET /v3/events/arcs?arcIds=<arcId>
-> the arc's summary and the ids of the other threads in it.
Fetch them with GET /v3/events/storylines?storylineIds=<ids>
Read lastMaterialAt and status to judge whether the thread is still moving.
Research a Topic
What is happening around stablecoin regulation?
1. GET /v3/events/storylines?q=stablecoin%20regulation
-> threads about it, open and dormant, best match first, each with a summary.
Add status=open for only the ones still developing. Prices in a summary
are as of its lastMaterialAt, not now
2. GET /v3/events?q=stablecoin%20regulation&alertAction=alert
-> its flagged events, best match first
3. For a storyline whose arcId is set:
GET /v3/events/arcs?arcIds=<arcId>
-> the larger movement it belongs to
URL-encode q. For one asset rather than a topic, use entityIds: see
Search by Topic.
Check How an Account's Calls Ended
An account gets attention. Do its calls work, and what does it hold now?
1. GET /v3/people/accounts?limit=20
-> the 20 accounts others engage with most, each with its
track: alpha score, hit rate and average return over every position
2. For a handle you are considering:
GET /v3/calls/episodes?handle=<handle>&status=closed&from=<now-30d>&limit=30
-> the positions it held in the last 30 days that have since closed,
each with entryPrice, exitPrice, closeReason and the opening setup
3. GET /v3/calls/episodes?handle=<handle>&status=open&from=<now>
-> what it holds now
4. For the posts behind one episode:
GET /v3/calls?callIds=<calls[].callId from step 2>
-> each call's setup and thesis
- A long worked when
exitPriceis aboveentryPrice; a short, below. Skip episodes with a null price. closeReason: "expiry"means the account never closed it. ItsexitPriceis not one the account chose: count expiries apart.handletakes X accounts only. See Filtering by Account.
Spot New Contracts
Which addresses are being pasted right now, and what do we know about them?
1. GET /v3/market/crypto/trending-contracts?from=<now - 1h>&minMentions=5
-> addresses ranked by posts in the last hour, every source together
2. For a row whose asset is not null:
GET /v3/events?entityIds=<asset.id>&from=<now - 1d>
GET /v3/calls/positioning?entityId=<asset.id>
-> what is being said about it, and how accounts are positioned
3. For a row whose asset is null:
-> nobody has catalogued the address yet. Re-read trending contracts
later; once it has an id, step 2 works