Skip to main content

epovest

The official Python SDK for the Epovest API.

With Epovest, businesses make AIs recommend them. From the questions their customers ask to the sources that shape the answers, everything is measured, dated and verifiable. And everything leads to action: where to appear, what to fix, and proof of what changed.

The assistants it measures are ChatGPT, Claude, Gemini, Perplexity, Mistral and Grok.

The whole REST API v1 is here, one method per route, generated from the OpenAPI 3.1 description the API serves at epovest.com/docs/openapi.json.

  • Synchronous and asynchronous clients, on httpx.
  • Typed: every named object of the API is a TypedDict, and every method says what it answers.
  • Query parameters are spelled out as keyword arguments, so your editor lists them.

Install

pip install epovest

Python 3.11 and above.

Quickstart

import os

from epovest import Epovest

epovest = Epovest(api_key=os.environ["EPOVEST_API_KEY"])

# What is already measured
trackers = epovest.list_trackers()["trackers"]

# Set up a new measurement, and start it
tracker = epovest.create_tracker(
    body={
        "title": "Market watch",
        "prompts": ["Which GEO tracking solution should I choose?"],
        "engines": ["chatgpt", "claude"],
        "frequency": "weekly",
        "resolution": "hd",
        "keywords": [{"keyword": "Epovest", "favorite": True}],
        "analysts": ["keyword_presence", "share_of_voice"],
    }
)["tracker"]

epovest.start_tracker(tracker["id"])

# Read the series
scores = epovest.get_results(tracker["id"], analyst="keyword_presence")["scores"]

Asynchronous, same names:

from epovest import AsyncEpovest

async with AsyncEpovest(api_key=os.environ["EPOVEST_API_KEY"]) as epovest:
    answers = await epovest.get_responses(tracker_id, engine="claude", tone="negative")

Authentication

Every call carries an API key of your account. The owner creates one in the app, at /account/api-keys; the secret starts with epo_ and is shown once, at creation.

Scopes are chosen at creation: read, which every key has, and write, for creating and changing things. Each method names the scope it takes in its docstring.

epovest = Epovest(
    api_key=os.environ["EPOVEST_API_KEY"],
    timeout=30.0,
    max_retries=2,
    headers={"User-Agent": "acme-reporting/2.1"},
)

The client holds a connection pool: use it as a context manager, or call close() (aclose() on the asynchronous one) when you are done.

What you can call

70 methods, named after the operation they wrap, and the name is the same one the MCP tool carries:

Area Methods
Trackers list_trackers, get_tracker, create_tracker, update_tracker, start_tracker, survey_now, pause_tracker, archive_tracker
Results list_surveys, get_results, get_responses
Keyword discovery list_keyword_discoveries, accept_keyword_discovery, dismiss_keyword_discovery, restore_keyword_discovery
Projects and canon list_projects, create_project, rename_project, get_canon, update_project_canon, archive_project, get_link_targets, set_link_targets
Surfaces list_surfaces, create_surface, update_surface, tick_surface_checklist, add_surface_check, update_surface_check, delete_surface_check, restore_surface_check, delete_surface, restore_surface, convert_surface_to_corroboration
Corroborations list_corroborations, create_corroboration, update_corroboration, verify_corroboration, set_registry_monitoring, archive_corroboration, convert_corroboration_to_surface, list_corroboration_candidates, dismiss_corroboration_candidate
Logbook get_logbook, create_logbook_entry, update_logbook_entry, delete_logbook_entry, restore_logbook_entry
Quests list_quests, create_quest, update_quest, complete_quest, dismiss_quest, reopen_quest
Competitor scans list_competitor_scans, get_competitor_scan, create_competitor_scan, start_competitor_scan, update_competitor_scan
Atlas of sources list_sources, get_source, list_source_channels
Account, credits, usage get_account_settings, update_account_settings, get_credits, topup_credits, get_usage
Support contact_support, list_support_threads, get_support_thread

Path parameters come first, the query parameters follow as keyword arguments, and a request body goes in body:

epovest.update_surface(surface_id, body={"languages": ["en", "pt-br"]})
epovest.list_sources(domain="wikipedia.org", sort="aa_claude", per_page=100)

Types

Every named object of the API is exported as a TypedDict, and every method is annotated with what it answers:

from epovest import Credits, Tracker


def shortfall(credits: Credits) -> int:
    return max(0, credits["min_topup_minor"] - credits["available_minor"])

Pagination

GET /sources, GET /trackers/{id}/responses and GET /usage are paginated, and page is clamped: asking for page 99 of 3 answers page 3. paginate reads that the way the API intends, and stops on the last page:

for page in epovest.paginate(lambda page: epovest.list_sources(page=page, per_page=100)):
    for source in page["sources"]:
        print(source["domain"], source["engines"])

Errors

A refused call raises an EpovestError carrying the slug of the refusal. Branch on code, which is stable, rather than on the message, which is written for a person. Everything the envelope carries next to the two of the envelope stays readable in body:

from epovest import EpovestError

try:
    epovest.start_tracker(tracker_id)
except EpovestError as error:
    if error.code == "insufficient_credits":
        # The answer carries what a survey costs, what is available, and where to top up.
        print(error.body["cost_per_survey_minor"], error.body["available_minor"], error.body["top_up_url"])
    raise

A request that never reached Epovest raises an EpovestConnectionError, whose cause carries what the platform reported.

Retries. A 429 rate_limited is sent again whatever the verb, after the wait the Retry-After header names: the budget refuses the call before it runs. A network failure or a 5xx is sent again on reads alone, so a write that may have landed is yours to replay, when you decide it should be. max_retries sets how many times, and 0 turns it off.

Also available as MCP

The same surface is served as MCP tools at https://mcp.epovest.com/mcp, for agents that speak the Model Context Protocol: one tool per route, the same keys and the same error envelopes, and the tool names are the method names of this SDK. See epovest.com/docs/api.md.

Reference

License

MIT

Metadata

Release files for epovest 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for epovest 1.0.1
File Size Uploaded
epovest-1.0.1.tar.gz 47.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for epovest 1.0.1
File Interpreter ABI Platform
epovest-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 88.1 kB

Release files / epovest-1.0.1.tar.gz

Download URL epovest-1.0.1.tar.gz
Size 47.4 kB
Tags Source
SHA-256 checksum
How to use checksums
d4441d3cec1bae9d53491216d0bedaa1affc4d87fa2a4ac399c5895a36e8e069
BLAKE2b-256 checksum
How to use checksums
4179f50b57d004be2952cb63c4d763050546761ce86aeb4148cfbd2d6c294db8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / epovest-1.0.1-py3-none-any.whl

Download URL epovest-1.0.1-py3-none-any.whl
Size 40.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e8e19f1446792dd9553a0d5bfaf98d34e58dac14a68fc2ef063c2c292a325081
BLAKE2b-256 checksum
How to use checksums
684520ecbe6d6d5c6f67db0e1019738e54e2ec0222ad2e8a48c4e345e0282041
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page