Skip to main content

API v3 New

API v3 is the data stack that powers agent awareness. Elfa monitors news and market chatter worldwide, across crypto and equities, and turns it into events, positions and rankings, so your agents get the latest real-time context and react faster when the stakes are high.

QuestionEndpoint (GET)Returns
Which id is this?/v3/entitiesThe id every other endpoint takes, from a ticker, name, handle, address, CoinGecko id, FIGI or CIK
What is happening?/v3/eventsEvents: what happened, what it names, how prices reacted. Searchable by topic
/v3/events/storylinesOne development followed over days
/v3/events/arcsStorylines grouped into a larger movement
Where is attention?/v3/market/crypto/mindshare, …/equity/mindshareAssets ranked by share of attention, with hot
/v3/market/crypto/trending-contractsContract addresses ranked by how many posts pasted them
Which way does the crowd lean?/v3/market/crypto/call-book, …/equity/call-bookThe whole market's long/short lean, hour by hour
/v3/calls/positioningOpen longs and shorts on one asset, now
What are accounts doing?/v3/callsEvery post that takes or changes a position
/v3/calls/episodesEach position from open to close, with prices and the author's track record
Who is worth reading?/v3/people/accountsAccounts ranked by standing
What can my key do?/v3/key-statusPlan, credits, limits and how far back it reads

No endpoint returns post text. Events carry a written title and summary, and link to each post behind them.

New to the terms? Concepts shows each one with a real example.

Quickstart​

Resolve Bitcoin, read its last day of events, then see how accounts are positioned on it.

BASE=https://api.elfa.ai

# 1. Resolve. Check the name: the first match may not be the asset you meant.
ID=$(curl -s "$BASE/v3/entities?q=btc&entityType=token&limit=1" \
-H "x-elfa-api-key: $ELFA_API_KEY" | jq -r '.entities[0].id')

# 2. Its events of the last 24 hours. from is required, in seconds.
# An empty list is a quiet range, not an error.
FROM=$(( $(date +%s) - 86400 ))
curl -s "$BASE/v3/events?entityIds=$ID&from=$FROM&limit=10" \
-H "x-elfa-api-key: $ELFA_API_KEY"

# 3. Open longs and shorts on it right now.
curl -s "$BASE/v3/calls/positioning?entityId=$ID" \
-H "x-elfa-api-key: $ELFA_API_KEY"

See Choosing a Match before you rely on step 1, and Workflows for longer recipes.

Rules Every Endpoint Follows​

RuleIn short
AuthenticationSend x-elfa-api-key on every request
AccessPAYG, Grow and Enterprise keys
TimesUnix seconds, UTC, in requests and responses. Milliseconds are a 400: divide by 1000
Time rangesfrom is required, to defaults to now, both inclusive
History30 days, 60 days or 2 years back, by plan. An earlier from is cut, and servedFrom says where
PagingPass nextCursor back as cursor. No offset, no total
ListsParameters marked a list take several values, repeated or comma-separated. At most 30 ids
By ideventIds, storylineIds, arcIds, callIds and episodeIds fetch up to 30, with no from
ErrorsA bad parameter, or an unknown id in a filter, is a 400. Nothing matching is a 200 with an empty list

Authentication​

Send x-elfa-api-key: <your key> on every request. A 401 says why it failed:

messageFix
API key is requiredSend the header
Invalid or expired API keyCheck the key. A mistyped or revoked key gets this
Error validating API keyOur side. Retry

A 503 ERR_SERVICE_UNAVAILABLE means the key could not be checked just then, or, with q, that search is down. It says nothing about the key. Retry after a few seconds.

Access​

PAYG, Grow and Enterprise keys can call every v3 endpoint. A Free key can call only /v3/key-status. Get a key, or upgrade, in the Developer Portal. Each 403 names its next step:

403 readsWhenDo
The v3 API is free on the Pay-as-you-go and Grow plans. Upgrade at …A Free key, on any endpoint but /v3/key-statusUpgrade in the Developer Portal
API key does not have the required scope: …A paid key without this endpointEmail [email protected] with the requestId

Rate Limits​

A per-minute limit per key, set by the plan and shared with your /v2 requests. /v3/key-status returns it as credits.requestsPerMinute, and responses carry it in headers:

RateLimit-Limit: 60
RateLimit-Remaining: 59
RateLimit-Reset: 42

Over it, you get 429 ERR_RATE_LIMIT_EXCEEDED: wait RateLimit-Reset seconds. See Rate Limits for the limits per plan.

Time Ranges​

ParameterValue
fromUnix seconds. Required, except when fetching by id or searching
toUnix seconds. Defaults to now

There is no default range: leaving out from is a 400, from is required. Some endpoints read time their own way:

History​

PlanReads back
PAYG30 days
Grow60 days
Enterprise2 years

Counted from midnight UTC. /v3/key-status returns the start as historyFrom.

from before historyFrom  ->  cut to historyFrom, and servedFrom says so
to before historyFrom -> 400 "This plan answers from 1788307200 onwards."
an id older than it -> skipped when you fetch by id
  • servedFrom is on every list that takes from. It is null when you fetch by id without from, and on events with sort=relevant.
  • Storylines, arcs, call episodes and mindshare apply the limit as their pages say.
  • The limit moves at midnight UTC. A cursor from a range it cut then stops working: start again from the first page.

Paging​

{
"events": [ … ],
"nextCursor": "TUHFseJr.MjAy…",
"hasMore": true,
"servedFrom": 1790672305
}
  • Pass nextCursor back as cursor. hasMore: false and nextCursor: null mark the last page. There is no offset and no total.
  • A cursor belongs to its query. Change anything but limit and it is a 400, Invalid cursor…. Start again without it. Treat a cursor as opaque.
  • The list is named for what it holds: events, storylines, arcs, entities, bars, assets, contracts, calls, episodes, accounts.
  • order is desc (default) or asc where an endpoint takes it. Entities, mindshare and trending contracts take none.
EndpointsDefault limitMost
Events, storylines, arcs, calls, call episodes1030
Call books, mindshare, trending contracts, top accounts50200
Entities10200

Lists of Values​

?entityIds=<id1>,<id2>
?entityIds=<id1>&entityIds=<id2>

Only parameters marked a list take several values: eventClass=market,asset is a 400. A list of ids takes at most 30, and entityIds matches any of them.

Fetching by Id​

eventIds, storylineIds, arcIds, callIds and episodeIds take up to 30 ids you already hold:

  • No from, and no next page: everything found comes back at once.
  • An id we do not hold, or one older than your history, is skipped, not an error.
  • Other filters still apply, except with eventIds, which combines only with alertAction, order and sort=latest.

Errors​

Every error has the body { code, message, details?, errorId, requestId }. Branch on code or the status, not on message. The common ones:

You sentAnswerDo
No from400, from is requiredSend from
A range wholly before your history400, This plan answers from … onwards.Move to later
An unknown parameter400, Unrecognized: … in detailsFix or drop it. Unknown parameters are never ignored
A bad value: an unknown enum, milliseconds, from after to, a malformed id400 naming the field in detailsFix that field
A cursor from another query400, Invalid cursor…Start again without it
limit over the most400, limit must be 30 or lessLower it
An entity id that is not a UUID400, must be an id from /v3/entitiesResolve it with /v3/entities
A UUID we do not hold400, Unknown id: …Resolve it again
A person, project or organisation where an asset is needed400, … is not an asset family.Resolve with entityType=token or equity
A handle we do not hold, on calls or episodes400, Unknown handle: …Check the spelling
A filter that matches nothing200, an empty listWiden the range
q while search is down503, Search is unavailable right now…Retry, or drop q

Field Reference lists every status, and which are worth retrying.

Key Status​

GET /v3/key-status: what your key can do and what it has left. No scope, no parameters, and it answers even when credits run out.

{
"plan": "payg",
"billingMode": "deposit",
"owner": "user",
"scopes": ["key-status", "chat", "events", "calls", "entities"],
"credits": {
"limit": null,
"used": 407,
"remaining": 2223,
"resetsAt": null,
"requestsPerMinute": 60
},
"historyFrom": 1788307200
}

A PAYG key, scopes trimmed to 5 of its 25.

FieldMeaning
planpayg, grow or enterprise. A Free key reads payg, with no v3 scope in scopes
billingModedeposit: a prepaid balance. arrears: a subscription, billed after use
owneruser or org: whose account these numbers are. Its keys share them
scopesEvery scope the key holds, /v2 included. They follow the plan
credits.limit, credits.resetsAtThe monthly limit and its reset (1st of the month, UTC). null on prepaid
credits.usedCredits used this month, UTC
credits.remainingPrepaid: the balance. Subscription: limit minus used, never below 0
credits.requestsPerMinuteThe per-minute limit on this key
historyFromThe earliest time this plan reads. See History

Sending any parameter is a 400. An Enterprise key not set up yet gets 403, Enterprise API keys require explicit configuration…: email [email protected] with the requestId.