pitchmentor
Official Python SDK for the Pitch Mentor API (https://api.pitchmentor.net/v1).
Python 3.11+, synchronous, built on requests. Responses are plain dicts typed with TypedDicts (Call, Lead,
Page[Call], …), so editors and mypy check them.
API reference: https://pitchmentor.net/docs
Install
pip install pitchmentor
Authentication
Create a team API key (pm_live_…) in the Pitch Mentor dashboard. It is sent as Authorization: Bearer pm_live_….
The client reads PITCHMENTOR_API_KEY (and optionally PITCHMENTOR_BASE_URL) from the environment, or takes them as
arguments. Each key has scopes (calls:read, leads:write, …); every method's docstring names the scope it needs.
from pitchmentor import PitchMentor
pm = PitchMentor() # or PitchMentor("pm_live_…", base_url=..., max_retries=2, timeout=60.0)
The client holds a requests.Session; use it as a context manager (with PitchMentor() as pm:) or call pm.close().
Quick start
me = pm.get_me()
detail = pm.get_call("call_id")
overview = pm.get_analytics_overview(period="30d")
per_member = pm.get_analytics_by_member(period="30d")
pm.upsert_lead({"name": "Ada Lovelace", "externalId": "crm-42", "email": "ada@example.com"})
pm.update_team_config({"toneGuidelines": "Friendly, concise."})
team = pm.get_team_config()
billing = pm.get_billing_status()
usage = pm.list_member_usage()
referrals = pm.get_referral_stats()
csv = pm.export_calls(format="csv")
pm.list_calls(from_="2026-01-01", archived=True) # `from` is `from_` in Python
Every API operation is a method named after its operationId in snake_case (list_calls, get_call,
create_webhook_endpoint, …). pm.request(method, path, query=..., body=...) reaches endpoints newer than the SDK.
Pagination
List methods return one page: {"data": [...], "has_more": bool, "next_cursor": str | None}. Pass next_cursor as
cursor for the next page, or use the …_iter method, which walks every page:
page = pm.list_calls(period="7d", limit=50)
for call in pm.list_calls_iter(period="7d"):
print(call["id"], call["prospectName"])
Paginated: list_calls, list_leads, list_api_keys, list_webhook_endpoints, list_webhook_deliveries.
Retries, timeouts and idempotency
429, 5xx and connection errors are retried (max_retries, default 2) with exponential backoff, honoring retry-after.
Every POST carries an Idempotency-Key, generated unless you pass one and reused across retries, so a retried POST never
runs twice. Pass your own key to make a POST safe to repeat across processes:
pm.upsert_lead({"name": "Ada", "externalId": "crm-42"}, idempotency_key="import-42")
Errors
Non-2xx responses raise a PitchMentorError subclass with status, code (machine-readable, e.g. not_found,
insufficient_scope), message, headers and body: BadRequestError (400), AuthenticationError (401),
PermissionDeniedError (403), NotFoundError (404), ConflictError (409), UnprocessableEntityError (422),
RateLimitError (429, has retry_after seconds), InternalServerError (5xx). A request that never got a response
raises APIConnectionError.
from pitchmentor import NotFoundError, PitchMentorError
try:
pm.get_call("missing")
except NotFoundError:
print("no such call")
except PitchMentorError as e:
print(e.status, e.code, e.message)
Webhooks
Webhooks are signed with Standard Webhooks (webhook-id, webhook-timestamp,
webhook-signature). verify_webhook checks the signature against your endpoint's whsec_… secret, rejects timestamps
older than 5 minutes (tolerance=300), and returns the parsed event. Always pass the raw request body.
import os
from flask import Flask, request
from pitchmentor import verify_webhook, WebhookVerificationError
app = Flask(__name__)
@app.post("/hooks/pitchmentor")
def hook():
try:
event = verify_webhook(os.environ["PITCHMENTOR_WEBHOOK_SECRET"], request.headers, request.get_data())
except WebhookVerificationError:
return "", 400
if event["type"] == "call.completed":
print(event["data"]["id"])
return "", 204
Development
python3 -m venv .venv && .venv/bin/pip install -e '.[dev]'
.venv/bin/mypy && .venv/bin/python -m unittest discover -s tests
Regenerating from the API
src/pitchmentor/_generated.py is generated by codegen/generate.mjs from openapi.json, a copy of the
live spec at https://api.pitchmentor.net/v1/openapi.json. Don't edit it by hand:
scripts/regen.sh # download the live spec and regenerate (needs curl and Node 20+)
node codegen/generate.mjs # regenerate from the committed openapi.json (after changing the generator)
Everything else (transport, retries, errors, pagination, webhooks) is hand-written. The weekly Regen workflow runs the same script and opens a pull request when the live spec changes.
Releasing
- Bump
versioninpyproject.tomland__version__insrc/pitchmentor/_client.py(scripts/check-version.sh X.Y.Zchecks both), merge tomain. git tag vX.Y.Z && git push origin vX.Y.Z. The Release workflow tests, builds and publishes to PyPI with trusted publishing (environmentpypi, with attestations) and creates the GitHub Release.
Support
Docs · Status · Discord. Security issues: see the security policy.
License
Metadata
Release files for pitchmentor 0.1.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 | Provenance | Actions |
|---|---|---|---|---|
| pitchmentor-0.1.1.tar.gz | 18.9 kB | Without provenance | Details for pitchmentor-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pitchmentor-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for pitchmentor-0.1.1-py3-none-any.whl |
Total release size: 34.2 kB
Release files / pitchmentor-0.1.1.tar.gz
| Download URL | pitchmentor-0.1.1.tar.gz |
|---|---|
| Size | 18.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
07a0406d4ddc87ee147281a41422a7a71975493fac0584f466cc73ad0a8b27ca
|
|
BLAKE2b-256 checksum How to use checksums |
46a61fa6a61a6ec49168c18e475665f9b3ec8d974429d99328d48c5d628edda6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / pitchmentor-0.1.1-py3-none-any.whl
| Download URL | pitchmentor-0.1.1-py3-none-any.whl |
|---|---|
| Size | 15.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
299420829e09cbec83a29d0b6d3a3dc6ab117996133d847a9718ed5038de5c14
|
|
BLAKE2b-256 checksum How to use checksums |
8e3db4f114dda2f9ca9a862562efdac5fc0ce965e65679b9bebae4de0175f4e0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Security for pitchmentor 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.