Skip to main content

Python client for the Pyth Network Hermes price-oracle API (sync + async, SSE streaming).

Project description

pyth-hermes

A typed Python client for the Pyth Network Hermes price-oracle API. Sync and async clients, Pydantic v2 models, Server-Sent-Events price streaming with auto-reconnect, and a Decimal price helper.

  • Sync (HermesClient) and async (AsyncHermesClient) APIs over httpx
  • SSE streaming with reconnect + backoff
  • Graceful 429 rate-limit handling (retries that respect the 60s window)
  • Configurable base_url (production, beta, or paid providers) and optional API key from day one
  • mypy --strict clean, fully type-hinted, ships py.typed

Install

pip install pyth-hermes
# with the optional pandas helper:
pip install "pyth-hermes[pandas]"

Quickstart — BTC/USD price in under 5 lines

from pyth_hermes import HermesClient

client = HermesClient()
feed_id = client.get_feed_id("Crypto.BTC/USD")   # exact-symbol lookup
print(client.get_price_decimal(feed_id))         # -> Decimal("63952.82...")

Async + streaming

import asyncio
from pyth_hermes import AsyncHermesClient

BTC = "e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"

async def main():
    async with AsyncHermesClient() as client:
        async for update in client.stream_prices([BTC]):
            print(update.parsed[0].to_decimal())

asyncio.run(main())

Historical price

resp = client.get_price_at(1718900000, [BTC])   # unix timestamp
print(resp.parsed[0].to_decimal())

pandas

from pyth_hermes.pandas import updates_to_dataframe
df = updates_to_dataframe([client.get_latest_price([BTC])])

Prices and exponents

Pyth returns integer prices plus an exponent. The real value is price * 10**expo, computed exactly as a Decimal:

from pyth_hermes import price_to_decimal
price_to_decimal(6395282153102, -8)   # Decimal("63952.82153102")

RpcPrice.to_decimal() and ParsedPriceUpdate.to_decimal() are convenience wrappers.

Finding feed ids — use the EXACT symbol

/v2/price_feeds?query=btc returns deprecated / variant feeds (e.g. MBTC, XBTC) before the canonical one and matches substrings. get_feed_id() therefore matches on exact attributes.symbol:

client.get_feed_id("Crypto.BTC/USD")
# -> "e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"

🔴 Authentication (changes 2026-07-31)

Today the public endpoint needs no API key. From 2026-07-31 an API key becomes mandatory. This client accepts one from day one — pass it now to be ready:

client = HermesClient(api_key="YOUR_KEY")  # default: Authorization: Bearer YOUR_KEY

The exact header is not finalized publicly, so both the header name and scheme are configurable:

HermesClient(api_key="KEY", api_key_header="X-Api-Key", api_key_scheme="")  # -> X-Api-Key: KEY

Endpoints / base URLs

from pyth_hermes import HermesClient

HermesClient()                                           # production: https://hermes.pyth.network
HermesClient(base_url="https://hermes-beta.pyth.network")  # beta
HermesClient(base_url="https://your-paid-provider.example")  # Triton / P2P / extrnode / Liquify

You may also inject your own preconfigured httpx.Client / httpx.AsyncClient via client=... (e.g. for custom transports, proxies, or connection pools). In that case the request host is taken from your client, so set base_url on the client itself — passing both base_url= and client= raises a UserWarning because the constructor's base_url would be a no-op. The api_key is still applied per-request, so it works with an injected client.

import httpx
from pyth_hermes import HermesClient

http = httpx.Client(base_url="https://your-paid-provider.example", proxy="http://localhost:8080")
client = HermesClient(api_key="KEY", client=http)  # base_url comes from `http`

Rate limits

The public endpoint allows 10 requests / 10 seconds per IP. Exceeding it returns HTTP 429 for the next 60 seconds. The client retries 429 and 5xx responses with exponential backoff + jitter, honoring any Retry-After header and never exceeding the 60s rate-limit window per delay. Tune via max_retries, backoff_base, backoff_cap.

Not implemented

The TWAP endpoints (/v2/updates/twap/...) are intentionally omitted — the API returns HTTP 400 "deprecated and no longer available".

Development

pip install -e ".[dev]"
pytest                 # unit tests (no network)
pytest -m integration  # live smoke tests against production
mypy
ruff check .

License

MIT

Project details


Download files

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

Source Distribution

pyth_hermes-0.1.0.tar.gz (16.2 kB view details)

Uploaded Source

Built Distribution

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

pyth_hermes-0.1.0-py3-none-any.whl (12.8 kB view details)

Uploaded Python 3

File details

Details for the file pyth_hermes-0.1.0.tar.gz.

File metadata

  • Download URL: pyth_hermes-0.1.0.tar.gz
  • Upload date:
  • Size: 16.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for pyth_hermes-0.1.0.tar.gz
Algorithm Hash digest
SHA256 db34c55936c7af661cca472c273c4cc62619aa9ee880ca4e21712c9009446bbb
MD5 f5e19dd725b9b3af777ad17282053f31
BLAKE2b-256 4de670c9eb95fc6e3589a75e30302c1c33d24ea3a0709dc5e2b18bfd7e1c5f41

See more details on using hashes here.

File details

Details for the file pyth_hermes-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pyth_hermes-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for pyth_hermes-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5fb8e4140b1f1a2e5ee418194c608ef53aa7329800a1c2e905d4e3c06ffcbe87
MD5 c1ea19ebdaefd26084841ff865817bdd
BLAKE2b-256 5caabe5ad57573263291619a6e88576f3da78b3bbf61f5d23907cbcbef8575e8

See more details on using hashes here.

Supported by

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