| Name | pyplanhat JSON |
| Version |
0.2.1
JSON |
| download |
| home_page | None |
| Summary | Pythonic wrapper for the Planhat REST API |
| upload_time | 2025-11-11 13:35:57 |
| maintainer | None |
| docs_url | None |
| author | None |
| requires_python | >=3.10 |
| license | None |
| keywords |
api
crm
planhat
rest
sdk
wrapper
|
| VCS |
 |
| bugtrack_url |
|
| requirements |
No requirements were recorded.
|
| Travis-CI |
No Travis.
|
| coveralls test coverage |
No coveralls.
|
# 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
```bash
pip install pyplanhat
```
## Quick Start
### Async Usage (Recommended)
```python
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
```python
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](USAGE.md).
## Configuration
Set environment variables for convenient testing:
```bash
export PLANHAT_API_KEY="your-api-key"
export PLANHAT_API_BASE_URL="https://api.planhat.com" # optional
```
Or pass directly to the client:
```python
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 ID
- `create(resource)` - Create a new resource
- `update(id, resource)` - Update an existing resource
- `delete(id)` - Delete a resource
## Development
### Setup
```bash
# 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**:
1. โ๏ธ Write async code in `src/pyplanhat/_async/`
2. ๐ Generate sync code: `python scripts/generate_sync.py`
3. โ
Both versions tested identically
4. ๐ฆ 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](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.py` after 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:
1. [CLAUDE.md](CLAUDE.md) - Development workflow and commands
2. [docs/pyplanhat/PLAN.md](docs/pyplanhat/PLAN.md) - Phased development plan
3. [docs/pyplanhat/ARCHITECTURE.md](docs/pyplanhat/ARCHITECTURE.md) - Architecture details
## License
MIT License - see [LICENSE](LICENSE) for details.
## Support
For issues, questions, or contributions, please open an issue on GitHub.
Raw data
{
"_id": null,
"home_page": null,
"name": "pyplanhat",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "api, crm, planhat, rest, sdk, wrapper",
"author": null,
"author_email": "David D Lawson <david@lawson.dev>",
"download_url": "https://files.pythonhosted.org/packages/86/87/b7cfd5d17d9e58f01a7c8d8c2fdceceb5c4d293e7b657329bc88e48c114f/pyplanhat-0.2.1.tar.gz",
"platform": null,
"description": "# PyPlanhat SDK\n\nModern async-first Python SDK for the Planhat API.\n\n## Features\n\n- \ud83d\ude80 **Async-first architecture** with auto-generated sync support\n- \ud83d\udce6 **Built with modern Python tooling** (httpx, pydantic, uv)\n- \ud83d\udd12 **Type-safe** with full mypy support\n- \u2728 **Comprehensive error handling** with custom exception hierarchy\n- \ud83e\uddea **Extensively tested** with 97% coverage\n- \ud83d\udcda **Complete resource coverage** - Companies, EndUsers, Conversations\n- \ud83c\udfa8 **Fully extensible models** - Subclass and add your own typed fields\n\n## Installation\n\n```bash\npip install pyplanhat\n```\n\n## Quick Start\n\n### Async Usage (Recommended)\n\n```python\nimport asyncio\nfrom pyplanhat import AsyncPyPlanhat, Company\n\nasync def main():\n async with AsyncPyPlanhat(api_key=\"your-api-key\") as client:\n # List all companies\n companies = await client.companies.list()\n\n # Get a specific company\n company = await client.companies.get(\"company-id\")\n\n # Create a new company\n new_company = Company(\n name=\"Acme Corporation\",\n status=\"prospect\",\n custom={\"industry\": \"Technology\"}\n )\n created = await client.companies.create(new_company)\n\n # Work with end users\n users = await client.endusers.list(company_id=company.id)\n\n # Work with conversations\n conversations = await client.conversations.list(company_id=company.id)\n\nasyncio.run(main())\n```\n\n### Sync Usage\n\n```python\nfrom pyplanhat import PyPlanhat, Company\n\nwith PyPlanhat(api_key=\"your-api-key\") as client:\n # All the same methods work synchronously\n companies = client.companies.list()\n company = client.companies.get(\"company-id\")\n```\n\nFor detailed examples and advanced usage, see [USAGE.md](USAGE.md).\n\n## Configuration\n\nSet environment variables for convenient testing:\n\n```bash\nexport PLANHAT_API_KEY=\"your-api-key\"\nexport PLANHAT_API_BASE_URL=\"https://api.planhat.com\" # optional\n```\n\nOr pass directly to the client:\n\n```python\nclient = AsyncPyPlanhat(\n api_key=\"your-api-key\",\n base_url=\"https://api.planhat.com\"\n)\n```\n\n## Resources\n\nPyPlanhat provides complete CRUD operations for the following Planhat resources:\n\n- **Companies** - Manage customer companies with full lifecycle tracking\n- **EndUsers** - Manage contacts and end users within companies\n- **Conversations** - Track interactions, meetings, and communications\n\nEach resource supports:\n- `list()` - Get all resources (with optional filtering)\n- `get(id)` - Get a specific resource by ID\n- `create(resource)` - Create a new resource\n- `update(id, resource)` - Update an existing resource\n- `delete(id)` - Delete a resource\n\n## Development\n\n### Setup\n\n```bash\n# Clone repository\ngit clone https://github.com/ddlaws0n/pyplanhat.git\ncd pyplanhat\n\n# Install dependencies\nuv sync --all-groups\n\n# Run tests\nuv run pytest -v\n\n# Format code\nuv run ruff format .\n\n# Lint code\nuv run ruff check .\n\n# Type check\nuv run mypy src/\n```\n\n### Architecture\n\nPyPlanhat uses an **async-first DRY architecture**:\n\n1. \u270f\ufe0f Write async code in `src/pyplanhat/_async/`\n2. \ud83d\udd04 Generate sync code: `python scripts/generate_sync.py`\n3. \u2705 Both versions tested identically\n4. \ud83d\udce6 Zero duplication of business logic\n\nThe synchronous version is automatically generated from the async source using `unasync`, ensuring perfect parity between both APIs.\n\n### Development Guidelines\n\nSee [CLAUDE.md](CLAUDE.md) for detailed development guidelines and workflow.\n\nKey principles:\n- **Never edit** files in `_sync/` directories (they're auto-generated)\n- **Always run** `python scripts/generate_sync.py` after modifying async code\n- **Maintain test parity** between async and sync test suites\n- **Follow the phased plan** in `docs/pyplanhat/PLAN.md`\n\n### Project Structure\n\n```\nsrc/pyplanhat/\n\u251c\u2500\u2500 _async/ # Async source code (write here)\n\u2502 \u251c\u2500\u2500 client.py # Main async client\n\u2502 \u2514\u2500\u2500 resources/ # Async resource implementations\n\u251c\u2500\u2500 _sync/ # Generated sync code (never edit)\n\u2502 \u251c\u2500\u2500 client.py # Generated sync client\n\u2502 \u2514\u2500\u2500 resources/ # Generated sync resources\n\u251c\u2500\u2500 _exceptions.py # Custom exception hierarchy\n\u2514\u2500\u2500 __init__.py # Public API exports\n\ntests/\n\u251c\u2500\u2500 _async/ # Async tests (write here)\n\u2514\u2500\u2500 _sync/ # Generated sync tests (never edit)\n```\n\n## Roadmap\n\n- **Phase 0**: Foundation (exception hierarchy, client shell, code generation) \u2705 **Complete**\n- **Phase 1**: Companies resource implementation \u2705 **Complete**\n- **Phase 2**: EndUsers and Conversations resources \u2705 **Complete**\n- **Phase 3**: Documentation (mkdocs, API reference) \ud83d\udea7 **In Progress**\n- **Phase 4**: Release to PyPI \u2705 **Complete** (v0.1.0 published)\n\n## Contributing\n\nThis project follows strict architectural patterns and phased development. Please review:\n\n1. [CLAUDE.md](CLAUDE.md) - Development workflow and commands\n2. [docs/pyplanhat/PLAN.md](docs/pyplanhat/PLAN.md) - Phased development plan\n3. [docs/pyplanhat/ARCHITECTURE.md](docs/pyplanhat/ARCHITECTURE.md) - Architecture details\n\n## License\n\nMIT License - see [LICENSE](LICENSE) for details.\n\n## Support\n\nFor issues, questions, or contributions, please open an issue on GitHub.\n",
"bugtrack_url": null,
"license": null,
"summary": "Pythonic wrapper for the Planhat REST API",
"version": "0.2.1",
"project_urls": {
"Bug Tracker": "https://github.com/ddlaws0n/pyplanhat/issues",
"Documentation": "https://github.com/ddlaws0n/pyplanhat#readme",
"Homepage": "https://github.com/ddlaws0n/pyplanhat",
"Repository": "https://github.com/ddlaws0n/pyplanhat.git"
},
"split_keywords": [
"api",
" crm",
" planhat",
" rest",
" sdk",
" wrapper"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "784ec43226379e74726c3f06dca8bd20988befe9a40a6dacd8bc68e0fa2928da",
"md5": "c968cfd9d085f391932769fcd32b05de",
"sha256": "e62d6d74478da09c35a97bb0bb5c17f4069c5d6dbed0a03188bdd3b66e5cdc48"
},
"downloads": -1,
"filename": "pyplanhat-0.2.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "c968cfd9d085f391932769fcd32b05de",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 21872,
"upload_time": "2025-11-11T13:35:56",
"upload_time_iso_8601": "2025-11-11T13:35:56.108906Z",
"url": "https://files.pythonhosted.org/packages/78/4e/c43226379e74726c3f06dca8bd20988befe9a40a6dacd8bc68e0fa2928da/pyplanhat-0.2.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "8687b7cfd5d17d9e58f01a7c8d8c2fdceceb5c4d293e7b657329bc88e48c114f",
"md5": "ff2aded13755e0cb53e9457ad5d96fec",
"sha256": "5fbe214d62668f92302d88683cdd8c10c4379c9c9a3dc3e2af80c749a59761fd"
},
"downloads": -1,
"filename": "pyplanhat-0.2.1.tar.gz",
"has_sig": false,
"md5_digest": "ff2aded13755e0cb53e9457ad5d96fec",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 162151,
"upload_time": "2025-11-11T13:35:57",
"upload_time_iso_8601": "2025-11-11T13:35:57.385514Z",
"url": "https://files.pythonhosted.org/packages/86/87/b7cfd5d17d9e58f01a7c8d8c2fdceceb5c4d293e7b657329bc88e48c114f/pyplanhat-0.2.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-11-11 13:35:57",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ddlaws0n",
"github_project": "pyplanhat",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "pyplanhat"
}