Skip to main content

Official Python client for the Neudata Developer API.

Project description

neudata-api-client

A Python client for the Neudata Developer API. It lets you search and retrieve dataset metadata, additional datasets, filters, and DDQs — and ships with resilient defaults: it retries dropped connections, backs off and honours Retry-After on rate limits (429), and auto-paginates list endpoints.

Installation

pip install neudata-api-client

For development (using uv):

git clone https://github.com/neudata/neudata-api-client
cd neudata-api-client
uv sync

Authentication

The API authenticates with two headers, Email and Api-Token. Your token is available at https://www.neudata.co/users/edit.

Provide them via environment variables (recommended):

export NEUDATA_EMAIL="you@example.com"
export NEUDATA_API_TOKEN="your-api-token"

…or pass them directly to the client:

from neudata import NeudataClient

client = NeudataClient(email="you@example.com", api_token="your-api-token")

A .env.example is included as a template.

Quickstart

from neudata import NeudataClient

with NeudataClient() as client:
    # Search a single page of datasets
    results = client.search_datasets(q="satellite", per_page=10)

    # Or iterate over *every* matching dataset (pagination handled for you)
    for dataset in client.iter_datasets(equity_region=["uk", "europe"]):
        print(dataset["id"], dataset["title"])

    # Fetch the full detail record for one dataset
    detail = client.get_dataset(1234)

API reference

Method Endpoint Description
search_datasets(**filters) GET /datasets One page of dataset search results
iter_datasets(per_page=99, **filters) GET /datasets Iterate all datasets across pages
get_dataset(id) GET /datasets/{id} Full dataset detail
list_filters() GET /filters Available filter parameter names
get_filter_options(name) GET /filters/{name} Allowable options for a filter
search_additional_datasets(**filters) GET /additional-datasets One page of additional datasets
iter_additional_datasets(per_page=99, **filters) GET /additional-datasets Iterate all additional datasets
get_additional_dataset(id) GET /additional-datasets/{id} Full additional-dataset detail
list_ddqs(page, per_page) GET /ddqs List DDQs (Sentry subscribers)
iter_ddqs(per_page=99) GET /ddqs Iterate all DDQs
get_ddq(id) GET /ddqs/{id} DDQ detail + 10-minute download URL

Filters

Search methods accept the documented query parameters as keyword arguments, e.g. q, page, per_page, sort, sort_by, source, from_date, data_provider_id, and the array filters equity_region, asset_class, combined_dataset_types, frequency, history, subscription_price, report_type, feed_type, output_format, esg_topics, filter_labels, ticker_indices, and more.

Array filters are passed as Python lists and serialized into the repeated name[] form the API expects:

client.search_datasets(asset_class=["public-equity", "fixed-income"])
# -> GET /datasets?asset_class[]=public-equity&asset_class[]=fixed-income

Use client.list_filters() and client.get_filter_options(name) to discover the valid values for each filter at runtime.

Resilience: retries, backoff & rate limits

The client is configured on construction:

NeudataClient(
    timeout=30,                  # per-request timeout (seconds)
    max_retries=5,               # retries for dropped connections / 5xx
    backoff_factor=0.5,          # exponential backoff base
    max_backoff=60,              # cap on any single backoff sleep
    max_rate_limit_retries=10,   # retries specifically for 429 responses
    requests_per_minute=90,      # client-side throttle (0 disables it)
)
  • Dropped/closed connections (and timeouts and 5xx server errors) are retried up to max_retries times with jittered exponential backoff.
  • 429 rate limits are retried up to max_rate_limit_retries times. The Retry-After header is honoured when present; otherwise exponential backoff is used. When retries are exhausted a RateLimitError is raised.
  • A built-in client-side throttle keeps the sustained request rate below requests_per_minute (the API guideline is ~100/min) so bulk jobs avoid tripping the limiter in the first place.

Enable logging to see retry/backoff activity:

import logging
logging.getLogger("neudata").setLevel(logging.INFO)

Exceptions

All exceptions derive from neudata.NeudataError:

  • AuthenticationError401/403 (bad credentials; not retried)
  • NotFoundError404
  • RateLimitError429 retries exhausted (carries retry_after)
  • NeudataAPIError — other unexpected API responses (carries status_code, response_body)

Example: download the whole catalogue

A console script is installed with the package:

# Dump all datasets + additional datasets to neudata_export.json
neudata-download

# Custom output, only datasets, with full per-item detail records
neudata-download --output datasets.json --datasets-only --details

# Filter by date or free text
neudata-download --from-date 2026-01-01 --query "credit card"

Run neudata-download --help for all options. A minimal, readable version using the library directly is in examples/download_all.py:

python examples/download_all.py out.json

The output JSON has the shape:

{
  "datasets": [ ... ],
  "additional_datasets": [ ... ]
}

Development

uv sync             # create the venv and install deps + dev tools
uv run pytest       # run the test suite (no network calls)

Tests use responses to mock the API and a monkeypatched sleep, so they run instantly and offline.

There is also an opt-in live smoke test that hits every endpoint against the real API. It is excluded from the default run and requires credentials:

export NEUDATA_EMAIL="you@example.com"
export NEUDATA_API_TOKEN="your-api-token"
uv run pytest -m smoke -v      # hits the real Neudata API

(The DDQ checks skip automatically if your account isn't a Sentry subscriber.)

Releasing to PyPI

uv build                          # build sdist + wheel into dist/
uvx twine check dist/*            # validate metadata / long description

# Test upload first
uv publish --publish-url https://test.pypi.org/legacy/ --token "$TEST_PYPI_TOKEN"

# Then the real thing
uv publish --token "$PYPI_TOKEN"

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

neudata_api_client-0.2.0.tar.gz (11.4 kB view details)

Uploaded Source

Built Distribution

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

neudata_api_client-0.2.0-py3-none-any.whl (14.4 kB view details)

Uploaded Python 3

File details

Details for the file neudata_api_client-0.2.0.tar.gz.

File metadata

  • Download URL: neudata_api_client-0.2.0.tar.gz
  • Upload date:
  • Size: 11.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.2

File hashes

Hashes for neudata_api_client-0.2.0.tar.gz
Algorithm Hash digest
SHA256 fcea3504e5002c5d3c78a4c63a37e892c201dff160be30ffe0b7f85eac07214b
MD5 a7d1c31a277355d14a4c7d1ce3773eed
BLAKE2b-256 769d4685d16ec258fdd22cd33822a4ab45dfafbeb9562bfc26b9f8a9c53391e4

See more details on using hashes here.

File details

Details for the file neudata_api_client-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for neudata_api_client-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4f620f613d3212eb12435f4cc67bc64656a5d1f51583305691098596420ddc01
MD5 083b9e1569526fb591bb1d4425c49be7
BLAKE2b-256 52ed96c7193516c9d7a6dbb907c08bc927a60d1497db1b0ae087d3a41b14785c

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