pivotalpath
Python wrapper around the PivotalPath v2 HTTP API. Returns
pandas.DataFrame when pandas is installed, otherwise plain
list[dict]. Single hard dependency: requests.
Install
# Core install - pulls `requests`
pip install pivotalpath
# With pandas extra - calls return DataFrames
pip install "pivotalpath[pandas]"
Without the [pandas] extra, calls return plain list[dict].
Configure
Set the API key via env var or call:
import os
os.environ['PIVOTALPATH_API_KEY'] = 'pp-...'
# OR
import pivotalpath as pp
pp.set_api_key('pp-...')
The base URL defaults to the production API
(https://apis.pivotalpath.com/resources/api/v2/). Point at a local
dev server (or staging) via the PIVOTALPATH_BASE_URL env var or
pp.set_base_url(...).
Without a key
No key set? The two free endpoints — index_catalog and index_return
— are served straight from the public dataset
(github.com/pivotalpath/publicdata), so they work out of the box with
no signup:
import pivotalpath as pp # no key needed
idx = pp.index_catalog()
ret = pp.index_return(id='iHFC', date_min='202001', pivot=True, columns='name')
All the usual query options (select, id, date window, filters,
pivot) apply — they're evaluated locally against the dataset. The data
is fetched once per process and cached. Any paid endpoint raises
PivotalPathError('ApiKeyRequired', …) until you set a key. (Override
the dataset location with PIVOTALPATH_PUBLICDATA_URL if you've forked
it.)
Use
import pivotalpath as pp
# Free, no key needed (served from the public dataset):
indices = pp.index_catalog()
rets = pp.index_return(date_min='202401', date_max='202412',
pivot=True, columns='name')
# Paid endpoints — set your key, then call any endpoint by name.
pp.set_api_key('pp-...')
rows = pp.get('your_endpoint', some_filter='value', select=['id', 'name'])
rows = pp.your_endpoint(some_filter='value') # identical, via shortcut
Endpoint discovery. This package is intentionally schema-agnostic — it ships no list of endpoints or columns. Which endpoints you can call (and their columns) comes from your API reference at https://apis.pivotalpath.com (the Reference tab), not from this package. Any
pp.<name>(...)is shorthand forpp.get('<name>', ...). The two free endpoints,index_catalogandindex_return, are the exception: their data is public.
Discover endpoints from Python
The reference is served live by the API, so these calls need a network connection and always match the current service:
pp.help() # how to get started, and where the full reference lives
pp.reference() # one row per endpoint you can use: name, group, tier, parameters
pp.reference(raw=True) # the complete OpenAPI document (dict)
Without an API key you see the public edition (the free endpoints). With a
valid key (pp.set_api_key('pp-...')) you see the complete edition, the same
document as the Reference tab and the PDF.
Errors
A non-null envelope error block raises PivotalPathError carrying the
type, message, and HTTP status code. Calling a paid endpoint without a key
raises PivotalPathError('ApiKeyRequired', …) with a pointer to where to
get one.
from pivotalpath import PivotalPathError
try:
rows = pp.index_return(id='iHFC')
except PivotalPathError as e:
print(e.type, e.message, e.status_code)
Cleaner errors in notebooks (opt-in)
By default PivotalPathError prints a full Python traceback like any
other exception. In an interactive notebook you usually just want to see
what's wrong. Opt in once:
import pivotalpath as pp
pp.install_excepthook()
After that, a bad column reads as a one-liner instead of a stack trace:
>>> pp.index_catalog(select=['bogus'])
Error: 'bogus' is not a column on 'index_catalog'. Try: abstract, id, name
The hook covers plain Python REPL, IPython, and Jupyter. Pass
force=True to install in scripts where you'd rather log a one-liner
than dump a stack. Reverse with pp.uninstall_excepthook().
The package does not auto-install on import — silently changing
sys.excepthook as a side effect of import is considered bad form
(it surprises collaborators, collides with other tools like
rich.traceback, and hides debug info). It's an explicit one-line
opt-in.
Multiple keys / multiple environments
The module-level shortcuts share a singleton Client. For two keys
in one process (or to point at a different base URL), instantiate
clients explicitly:
from pivotalpath import Client
prod = Client(api_key='pp-prod...', base_url='https://apis.pivotalpath.com/resources/api/v2/')
dev = Client(api_key='pp-dev...', base_url='http://127.0.0.1:8044/resources/api/v2/')
a = prod.index_catalog()
b = dev.index_catalog()
Auto-routing by id prefix
pp.returns() (alias pp.mtd()) and pp.info() detect the asset
class from the leading character of each id and route to the matching
<class>_return or <class>_catalog endpoint:
| Prefix | Class | Examples |
|---|---|---|
i |
index | iHFC, iQNT |
df = pp.returns(id=['iHFC', 'iQNT'], start='202401', columns='name')
df = pp.mtd(id='iHFC') # alias of pp.returns
df = pp.info(id='iHFC') # catalog metadata for an id
Only index ids (i…) auto-route. For any other endpoint, name it
explicitly — pp.returns(api_class='…', …) or, most directly,
pp.get('<endpoint>', id=['my_slug']).
Catalog filters resolve to ids
The package recognises kwargs that belong on the matching <class>_catalog
table and resolves them to ids in one step — it fetches matching ids from
the catalog, then runs your query filtered by those ids, returned to you as
a single call:
# Filter by index name, then pull the matching return series:
df = pp.index_return(name='PivotalPath Composite%', start='202401', pivot=True)
Works for any non-catalog feature; pass id=… explicitly to bypass the
resolver.
Endpoints
This package does not enumerate endpoints. See the Reference tab at https://apis.pivotalpath.com for the endpoints and columns available to your subscription. Every endpoint is callable two equivalent ways:
pp.get('your_endpoint', **params) # generic
pp.your_endpoint(**params) # dynamic shortcut (same request)
index_catalog and index_return are free and work with no key (served
from the public dataset — see Without a key).
Common parameters
Same shape as the HTTP API:
select=['id', 'name']— restrict columnsid=['iHFC', 'iQNT']— restrict to a list of idsdate_min='202401',date_max='202412'— time-series windowpivot=True,columns='name'— wide-form output
License
Proprietary. Copyright (c) 2026 PivotalPath. All rights reserved. See LICENSE. Access to PivotalPath data is governed separately.
Metadata
Release files for pivotalpath 2.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pivotalpath-2.0.1.tar.gz | 26.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pivotalpath-2.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 53.6 kB
Release files / pivotalpath-2.0.1.tar.gz
| Download URL | pivotalpath-2.0.1.tar.gz |
|---|---|
| Size | 26.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
97e4e1e69682685ba9b06a4734b20ac2e3439578c9cd5fab9fd456ad95a6315f
|
|
BLAKE2b-256 checksum How to use checksums |
21f0eadd921babd6b748b4c5c216717fca424f4208afdbd9323db877945d1969
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.1
|
Release files / pivotalpath-2.0.1-py3-none-any.whl
| Download URL | pivotalpath-2.0.1-py3-none-any.whl |
|---|---|
| Size | 27.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
985c0ff9041f497dc598a089ddc2a9d436a1de0bf248a9d01c8d37c1c7a4cb69
|
|
BLAKE2b-256 checksum How to use checksums |
6680dce72e0a8a1197729aadd63a813f0d5c875e0afaa5eb708ffa8d75595f91
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.1
|