Skip to main content

Elfa AI Python SDK

PyPI version Python 3.9+ License: MIT

Official Python SDK for the Elfa API v2 — social intelligence, AI chat, and the Auto condition engine for crypto. Sync and async clients, fully typed with Pydantic.

Features

  • Social intelligence — trending tokens, mentions, narratives, smart stats, event summaries
  • AI chat — market analysis and conversational chat via client.chat, streamed via client.chat_stream
  • Auto condition engine — build EQL queries that watch markets and notify via client.auto
  • Sync and asyncElfaClient and AsyncElfaClient, same surface
  • Typed — Pydantic v2 models, full type hints
  • Robust — retries with backoff, typed errors, HMAC request signing

The SDK returns processed metadata and tweet links only — never raw tweet content. For raw tweets, call the X (Twitter) API directly using the returned links/ids.

Installation

pip install elfa-sdk

Quick start

Synchronous

from elfa import ElfaClient

client = ElfaClient(api_key="your-api-key")

trending = client.get_trending_tokens(time_window="24h")
for token in trending.data.data:
    print(token.token, token.current_count, f"{token.change_percent:+.1f}%")

mentions = client.get_keyword_mentions(keywords="bitcoin,ethereum", time_window="1h")
for mention in mentions.data:
    print(mention.link, mention.like_count)

answer = client.chat("What's the sentiment on Bitcoin today?")
print(answer.data.message)

Asynchronous

import asyncio
from elfa import AsyncElfaClient

async def main():
    async with AsyncElfaClient(api_key="your-api-key") as client:
        stats = await client.get_account_smart_stats("elonmusk")
        print(stats.data.smart_following_count)

asyncio.run(main())

Configuration

client = ElfaClient(
    api_key="your-api-key",
    base_url="https://api.elfa.ai",  # default (production)
    timeout=30.0,                    # per-request timeout, seconds
    retries=3,                       # retries for idempotent (GET) requests
    retry_delay=1.0,                 # base delay for exponential backoff
    hmac_secret=None,                # required for Auto mutations that are not plain notifications (see below)
    headers=None,                    # extra headers sent on every request
)

# Quick reachability/auth check
assert client.test_connection() is True

The Auto engine is also constructable standalone if that is all you need:

from elfa import AutoClient

auto = AutoClient(api_key="your-api-key", hmac_secret="your-hmac-secret")
auto.close()

The API key is sent as the x-elfa-api-key header on every request. Read it from the environment in your app:

import os
from elfa import ElfaClient

client = ElfaClient(api_key=os.environ["ELFA_API_KEY"])

Core data & chat

All methods exist on both ElfaClient (sync) and AsyncElfaClient (async).

Method Endpoint
ping() /v2/ping
get_api_key_status() /v2/key-status
get_trending_tokens(...) /v2/aggregations/trending-tokens
get_account_smart_stats(username) /v2/account/smart-stats
get_keyword_mentions(...) /v2/data/keyword-mentions
get_token_news(...) /v2/data/token-news
get_trending_cas_twitter(...) /v2/aggregations/trending-cas/twitter
get_trending_cas_telegram(...) /v2/aggregations/trending-cas/telegram
get_top_mentions(ticker, ...) /v2/data/top-mentions
get_event_summary(keywords, ...) /v2/data/event-summary
get_trending_narratives(...) /v2/data/trending-narratives
chat(message, ...) /v2/chat
chat_stream(message, ...) /v2/chat/stream

Time-ranged endpoints accept either time_window="24h" or both from_time and to_time (unix seconds).

Streaming chat (SSE)

chat_stream takes the same arguments as chat and yields one event per data: frame, ending on the terminating [DONE] frame. Requires a PAYG or Enterprise API key.

for event in client.chat_stream("What is the sentiment on SOL?"):
    if event.type == "text":
        print(event.content, end="")
    elif event.type == "complete":
        print("\ncredits:", event.creditsConsumed)

# async
async for event in async_client.chat_stream("What is the sentiment on SOL?"):
    print(event.type)

Event types are session_info, title, text, text_complete, status, credits, complete, invalid_request and error. Payload fields vary by type and are preserved as model extras.

Auto condition engine (client.auto)

Build EQL queries that watch conditions and fire actions (notify, webhook, telegram_bot, llm). Notification-only queries need no secret; any other mutation shape requires an hmac_secret.

query = {
    "query": {
        "conditions": {
            "AND": [{
                "source": "price", "method": "current",
                "args": {"symbol": "BTC", "exchange": "hyperliquid"},
                "operator": ">", "value": 250000,
            }]
        },
        "actions": [{"stepId": "notify", "type": "notify", "params": {"message": "BTC > 250k"}}],
        "expiresIn": "24h",
    },
    "title": "btc breakout alert",
}

client.auto.validate_query(query)
created = client.auto.create_query(query)
query_id = created.id or created.query_id

status = client.auto.get_query(query_id)
client.auto.cancel_query(query_id)
client.auto.delete_query(query_id)

Also available: chat, list_queries, drafts (list_drafts/get_draft/upsert_draft/delete_draft/validate_draft/convert_draft), list_sessions/get_session, list_executions/get_execution, and validate_symbol.

Builder Chat is dynamically priced, so it reports what the turn cost:

reply = client.auto.chat("Alert me when BTC breaks 100k")
print(reply.credits)  # e.g. 104 — same total as the x-elfa-credits header

Response shapes are extensible

Every response model sets extra="allow", so fields the API adds are kept as model extras rather than raising. Do the same in your own code — pinning an Elfa response with an exact-shape assertion (Pydantic extra="forbid", z.strictObject, additionalProperties: false) means the next additive field breaks your client even though the API stayed backwards compatible.

Streaming notifications (SSE)

for event in client.auto.stream_query(query_id):
    print(event.event, event.data)

# async
async for event in async_client.auto.stream_all():
    print(event.event, event.data)

HMAC signing

Auto mutations are signed when hmac_secret is set. The SDK builds the signature over timestamp + METHOD + mounted_path + body and sends x-elfa-timestamp and x-elfa-signature headers. Signing every mutation is safe, so passing hmac_secret is always fine. Generate a secret in the dev portal.

Error handling

from elfa import (
    ElfaAPIError,
    ElfaAuthenticationError,
    ElfaRateLimitError,
    ElfaValidationError,
    ElfaNetworkError,
)

try:
    client.get_trending_tokens(time_window="24h")
except ElfaAuthenticationError:
    ...  # bad/missing API key
except ElfaRateLimitError as e:
    print("retry after", e.retry_after, "reset", e.reset_time)
except ElfaValidationError as e:
    print("invalid params", e.validation_errors)
except ElfaNetworkError:
    ...  # connection problem
except ElfaAPIError as e:
    print("api error", e.status_code, e)

Idempotent (GET) requests are retried with exponential backoff on network errors, rate limits, and 5xx responses. Mutations are not retried automatically.

Development

git clone https://github.com/elfa-ai/elfa-sdk-python.git
cd elfa-sdk-python
pip install -e ".[dev]"

make check   # flake8 + mypy + pytest
make format  # black + isort

Live integration tests run only when ELFA_API_KEY is set (optionally ELFA_BASE_URL, ELFA_HMAC_SECRET); otherwise they skip.

Support

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

elfa_sdk-5.1.0.tar.gz (34.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

elfa_sdk-5.1.0-py3-none-any.whl (27.6 kB view details)

Uploaded Python 3

File details

Details for the file elfa_sdk-5.1.0.tar.gz.

File metadata

  • Download URL: elfa_sdk-5.1.0.tar.gz
  • Upload date:
  • Size: 34.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for elfa_sdk-5.1.0.tar.gz
Algorithm Hash digest
SHA256 d02885298ef62d9a3faebf6776be0963b65515b087f6d00e5f7044d863e01770
MD5 edabc758abac34badb59fdeb7c139350
BLAKE2b-256 00c154df5df5afcda223d7a5aa23dcf0b6240ed681e4cfba00369f603607bb29

See more details on using hashes here.

Provenance

The following attestation bundles were made for elfa_sdk-5.1.0.tar.gz:

Publisher: release.yml on elfa-ai/elfa-sdk-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file elfa_sdk-5.1.0-py3-none-any.whl.

File metadata

  • Download URL: elfa_sdk-5.1.0-py3-none-any.whl
  • Upload date:
  • Size: 27.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for elfa_sdk-5.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c12d5f234e86ce211f530fd2bd8c7d947df8459986f4ccbc9961a074cf5df49a
MD5 ddf1806abb0152d8a2c657885be99570
BLAKE2b-256 6e4f08e6ac89db8d66bc5fb53a1ceae2053eb9449e9fdadf6ca29b473a74c2f4

See more details on using hashes here.

Provenance

The following attestation bundles were made for elfa_sdk-5.1.0-py3-none-any.whl:

Publisher: release.yml on elfa-ai/elfa-sdk-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page