Skip to main content

Alerts with Auto

To be told when an event is written up, rather than polling GET /v3/events for it, create an Auto query with an events condition. The condition is a /v3/events filter that runs on every new event instead of once: it takes the endpoint's filter values and matches them the same way.

1. GET /v3/entities                    -> the entity id
2. GET /v3/events ... &from=<now - 1d> -> what the condition would have fired on
3. POST /v2/auto/queries/validate -> errors, warnings, estimated cost
4. POST /v2/auto/queries -> the query, active
5. GET /v3/events?eventIds=<id> -> the detail of each event it fires on

1. Preview the Query​

Run the query over the last day. What it returns is what a condition with the same filters would have fired on:

GET /v3/entities?q=eth&entityType=token&limit=1
-> entities[0].id: Ethereum

GET /v3/events?entityIds=<ETH id>&implication=bearish&from=<now - 1d>
-> the bearish ETH events of the last day. Too many? Add eventType or
alertAction=alert. None? Drop a filter

The /v3 endpoints need a Pay-as-you-go, Grow or Enterprise key. Without one, skip the preview, name the entity by ticker or name, and read the Validate response to see which entity it resolved to.

2. Turn It Into a Condition​

{ "source": "events", "args": { "entity": "<ETH id>", "implication": "bearish" } }
GET /v3/eventsevents conditionDifference
entityIds=<id>"entity": "<id>"One entity per condition. A ticker or a name also works, see Entity Routing
eventClass, eventType, implication, assetClass, noveltyThe same argument, the same valuesNone. assetClass lets through events that name no asset in both
alertAction=alert"alertAction": "alert"One value. Leave it out for both
Several entityIds, or a list of alertActionSeveral conditions under OR
q=<topic>"text": "<claim>" with minConfidenceq ranks events by topic. text is a claim each event must state, checked event by event for credits
from, to, order, sort, eventIds, hasStoryline, notable, arcIdNoneA condition watches events written up from its creation onwards

Every filter takes one value, and all filters you set must pass. The full mapping, and when to reach for text, is in From a /v3/events Query and Filters vs Text.

A filter-only condition consumes no credits. A condition with text consumes credits each time an event that passes its filters is checked against the claim.

3. Validate, Then Create​

Wrap the condition in a root AND or OR group, add an action, and put the whole plan under a top-level query key:

{
"title": "Bearish ETH news",
"description": "Notify on each bearish event about Ethereum.",
"query": {
"conditions": {
"AND": [
{ "source": "events", "args": { "entity": "<ETH id>", "implication": "bearish" } }
]
},
"actions": [
{ "stepId": "step_1", "type": "notify", "params": { "message": "Bearish ETH event" } }
],
"expiresIn": "168h",
"repeat": { "cooldown": "15m", "maxTriggers": 20 }
}
}

Send it to Validate first, then, unchanged, to Create:

curl -X POST "https://api.elfa.ai/v2/auto/queries/validate" \
-H "x-elfa-api-key: $ELFA_API_KEY" \
-H "Content-Type: application/json" \
-d @query.json

curl -X POST "https://api.elfa.ai/v2/auto/queries" \
-H "x-elfa-api-key: $ELFA_API_KEY" \
-H "Content-Type: application/json" \
-d @query.json
  • Validate is required before Create, and free. It returns errors, warnings and an estimated cost. Read its warnings: when a name matches weaker alternatives, the warning names the entity you got.
  • Without repeat, the plan is one-shot: the first matching event fires it and moves it to a terminal state. With repeat, it fires once per matching event, spaced by cooldown, up to maxTriggers. See Repeat.
  • Actions in API key mode are webhook, notify, telegram_bot and llm. See HTTP Request Wrapper and Notifications.

4. When It Fires​

  • It fires on the events /v3/events serves, as they arrive, not on a polling interval, and on each event at most once.
  • Fresh events only. An event is matched only while it is less than an hour old. A new plan sees events from its creation onwards; nothing is replayed.
  • Not a first-post trigger. Events are written up from many posts, so they arrive minutes to hours after the first post. To be first, watch the account that breaks the news with a tweet condition.
  • A developing story can fire again. Later reporting on a story arrives as further events, and each can match. novelty: "new" does not remove them: most still read new. Use storylineId, below, or repeat.cooldown.

5. From the Alert Back to the Event​

The alert names the event, without its detail: match.eventId is the event's id in /v3/events, and match.title its alertTitle, with its classification and the entities it names. There is no summary and no link. Fetch the rest by id:

GET /v3/events?eventIds=<match.eventId>
-> summary, citedSources with their links, impacts (price reactions),
storylineId, and the entities with their ids

To act once per story, keep the storylineId of each event you act on and skip an event whose storylineId you already hold. storylineId is null on a call event and on an event not threaded into a story; treat those as stories of their own. The full payload is under Trigger Payload.