Pythonic wrapper for the Planhat REST API
Project description
PyPlanhat SDK
Modern async-first Python SDK for the Planhat API.
Features
- 🚀 Async-first architecture with auto-generated sync support
- 📦 Built with modern Python tooling (httpx, pydantic, uv)
- 🔒 Type-safe with full mypy support
- ✨ Comprehensive error handling with custom exception hierarchy
- 🧪 Extensively tested with 97% coverage
- 📚 Complete resource coverage - Companies, EndUsers, Conversations
- 🎨 Fully extensible models - Subclass and add your own typed fields
Installation
pip install pyplanhat
Quick Start
Async Usage (Recommended)
import asyncio
from pyplanhat import AsyncPyPlanhat, Company
async def main():
async with AsyncPyPlanhat(api_key="your-api-key") as client:
# List all companies
companies = await client.companies.list()
# Get a specific company
company = await client.companies.get("company-id")
# Create a new company
new_company = Company(
name="Acme Corporation",
status="prospect",
custom={"industry": "Technology"}
)
created = await client.companies.create(new_company)
# Work with end users
users = await client.endusers.list(company_id=company.id)
# Work with conversations
conversations = await client.conversations.list(company_id=company.id)
asyncio.run(main())
Sync Usage
from pyplanhat import PyPlanhat, Company
with PyPlanhat(api_key="your-api-key") as client:
# All the same methods work synchronously
companies = client.companies.list()
company = client.companies.get("company-id")
For detailed examples and advanced usage, see USAGE.md.
Configuration
Set environment variables for convenient testing:
export PLANHAT_API_KEY="your-api-key"
export PLANHAT_API_BASE_URL="https://api.planhat.com" # optional
Or pass directly to the client:
client = AsyncPyPlanhat(
api_key="your-api-key",
base_url="https://api.planhat.com"
)
Resources
PyPlanhat provides complete CRUD operations for the following Planhat resources:
- Companies - Manage customer companies with full lifecycle tracking
- EndUsers - Manage contacts and end users within companies
- Conversations - Track interactions, meetings, and communications
Each resource supports:
list()- Get all resources (with optional filtering)get(id)- Get a specific resource by IDcreate(resource)- Create a new resourceupdate(id, resource)- Update an existing resourcedelete(id)- Delete a resource
Development
Setup
# Clone repository
git clone https://github.com/ddlaws0n/pyplanhat.git
cd pyplanhat
# Install dependencies
uv sync --all-groups
# Run tests
uv run pytest -v
# Format code
uv run ruff format .
# Lint code
uv run ruff check .
# Type check
uv run mypy src/
Architecture
PyPlanhat uses an async-first DRY architecture:
- ✏️ Write async code in
src/pyplanhat/_async/ - 🔄 Generate sync code:
python scripts/generate_sync.py - ✅ Both versions tested identically
- 📦 Zero duplication of business logic
The synchronous version is automatically generated from the async source using unasync, ensuring perfect parity between both APIs.
Development Guidelines
See CLAUDE.md for detailed development guidelines and workflow.
Key principles:
- Never edit files in
_sync/directories (they're auto-generated) - Always run
python scripts/generate_sync.pyafter modifying async code - Maintain test parity between async and sync test suites
- Follow the phased plan in
docs/pyplanhat/PLAN.md
Project Structure
src/pyplanhat/
├── _async/ # Async source code (write here)
│ ├── client.py # Main async client
│ └── resources/ # Async resource implementations
├── _sync/ # Generated sync code (never edit)
│ ├── client.py # Generated sync client
│ └── resources/ # Generated sync resources
├── _exceptions.py # Custom exception hierarchy
└── __init__.py # Public API exports
tests/
├── _async/ # Async tests (write here)
└── _sync/ # Generated sync tests (never edit)
Roadmap
- Phase 0: Foundation (exception hierarchy, client shell, code generation) ✅ Complete
- Phase 1: Companies resource implementation ✅ Complete
- Phase 2: EndUsers and Conversations resources ✅ Complete
- Phase 3: Documentation (mkdocs, API reference) 🚧 In Progress
- Phase 4: Release to PyPI ✅ Complete (v0.1.0 published)
Contributing
This project follows strict architectural patterns and phased development. Please review:
- CLAUDE.md - Development workflow and commands
- docs/pyplanhat/PLAN.md - Phased development plan
- docs/pyplanhat/ARCHITECTURE.md - Architecture details
License
MIT License - see LICENSE for details.
Support
For issues, questions, or contributions, please open an issue on GitHub.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyplanhat-0.2.1.tar.gz.
File metadata
- Download URL: pyplanhat-0.2.1.tar.gz
- Upload date:
- Size: 162.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5fbe214d62668f92302d88683cdd8c10c4379c9c9a3dc3e2af80c749a59761fd
|
|
| MD5 |
ff2aded13755e0cb53e9457ad5d96fec
|
|
| BLAKE2b-256 |
8687b7cfd5d17d9e58f01a7c8d8c2fdceceb5c4d293e7b657329bc88e48c114f
|
Provenance
The following attestation bundles were made for pyplanhat-0.2.1.tar.gz:
Publisher:
release.yml on ddlaws0n/pyplanhat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyplanhat-0.2.1.tar.gz -
Subject digest:
5fbe214d62668f92302d88683cdd8c10c4379c9c9a3dc3e2af80c749a59761fd - Sigstore transparency entry: 692375770
- Sigstore integration time:
-
Permalink:
ddlaws0n/pyplanhat@808e698b8a97ad03e129d0fe7ba4f5418b574203 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/ddlaws0n
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@808e698b8a97ad03e129d0fe7ba4f5418b574203 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyplanhat-0.2.1-py3-none-any.whl.
File metadata
- Download URL: pyplanhat-0.2.1-py3-none-any.whl
- Upload date:
- Size: 21.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e62d6d74478da09c35a97bb0bb5c17f4069c5d6dbed0a03188bdd3b66e5cdc48
|
|
| MD5 |
c968cfd9d085f391932769fcd32b05de
|
|
| BLAKE2b-256 |
784ec43226379e74726c3f06dca8bd20988befe9a40a6dacd8bc68e0fa2928da
|
Provenance
The following attestation bundles were made for pyplanhat-0.2.1-py3-none-any.whl:
Publisher:
release.yml on ddlaws0n/pyplanhat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyplanhat-0.2.1-py3-none-any.whl -
Subject digest:
e62d6d74478da09c35a97bb0bb5c17f4069c5d6dbed0a03188bdd3b66e5cdc48 - Sigstore transparency entry: 692375774
- Sigstore integration time:
-
Permalink:
ddlaws0n/pyplanhat@808e698b8a97ad03e129d0fe7ba4f5418b574203 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/ddlaws0n
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@808e698b8a97ad03e129d0fe7ba4f5418b574203 -
Trigger Event:
push
-
Statement type: