|
1 | | -# pytally-sdk |
| 1 | +# PyTally SDK |
| 2 | + |
| 3 | +> Unofficial Python SDK for the [Tally.so](https://tally.so) API. |
2 | 4 |
|
3 | 5 | [](https://badge.fury.io/py/pytally-sdk) |
4 | 6 | [](https://pypi.org/project/pytally-sdk/) |
5 | 7 | [](https://opensource.org/licenses/Apache-2.0) |
| 8 | +[](https://pytally-sdk.fa.dev.br) |
| 9 | + |
| 10 | +--- |
6 | 11 |
|
7 | | -Unofficial Python SDK for the [Tally.so](https://tally.so) API. |
| 12 | +## Overview |
8 | 13 |
|
9 | | -> **Early Development**: This SDK is currently in early development and does not yet cover the entire Tally API. We're actively working on adding more endpoints and features. |
| 14 | +**PyTally SDK** is a lightweight, fully typed Python client for the [Tally.so API](https://tally.so). |
| 15 | +It provides a clean, Pythonic interface for authenticating, querying, and managing Tally resources -- without worrying about HTTP requests or pagination. |
| 16 | + |
| 17 | +### Implemented Resources |
| 18 | + |
| 19 | +[x] Users |
| 20 | +[x] Organizations |
| 21 | +[x] Forms |
| 22 | +[x] Workspaces |
| 23 | +[x] Webhooks |
| 24 | +[] MCP |
| 25 | +--- |
10 | 26 |
|
11 | 27 | ## Installation |
12 | 28 |
|
13 | | -Install the package using pip: |
| 29 | +### pip |
14 | 30 |
|
15 | 31 | ```bash |
16 | 32 | pip install pytally-sdk |
17 | 33 | ``` |
18 | 34 |
|
19 | | -Or using [uv](https://github.com/astral-sh/uv): |
| 35 | +### uv (recommended) |
20 | 36 |
|
21 | 37 | ```bash |
22 | 38 | uv add pytally-sdk |
23 | 39 | ``` |
24 | 40 |
|
| 41 | +**Requirements:** |
| 42 | +Python ≥ 3.11 |
| 43 | +`httpx` (auto-installed) |
| 44 | + |
| 45 | +--- |
| 46 | + |
25 | 47 | ## Quick Start |
26 | 48 |
|
27 | 49 | ```python |
28 | 50 | from tally import Tally |
29 | 51 |
|
30 | | -# Initialize the client with your API key |
31 | | -client = Tally(api_key="tly-your-api-key-here") |
| 52 | +client = Tally(api_key="tly_your_api_key_here") |
32 | 53 |
|
33 | | -# Get current user information |
34 | 54 | user = client.users.me() |
35 | | -print(f"Hello, {user.full_name}!") |
36 | | -print(f"Email: {user.email}") |
37 | | -print(f"Plan: {user.subscription_plan.value}") |
| 55 | +print(f"Hello, {user.full_name} ({user.email})") |
38 | 56 | ``` |
39 | 57 |
|
40 | 58 | ### With Context Manager |
41 | 59 |
|
42 | 60 | ```python |
43 | 61 | from tally import Tally |
44 | 62 |
|
45 | | -with Tally(api_key="tly-your-api-key-here") as client: |
46 | | - user = client.users.me() |
47 | | - print(f"Organization ID: {user.organization_id}") |
| 63 | +with Tally(api_key="tly_your_api_key_here") as client: |
| 64 | + for form in client.forms: |
| 65 | + print(f"{form.name} ({form.id})") |
48 | 66 | ``` |
49 | 67 |
|
50 | | -## Features |
| 68 | +--- |
51 | 69 |
|
52 | | -### Currently Implemented |
| 70 | +## Webhooks — Example Usage |
53 | 71 |
|
54 | | -- **Authentication**: Bearer token authentication with API versioning support |
55 | | -- **Users Resource**: |
56 | | - - `client.users.me()` - Get current authenticated user information |
57 | | -- **Error Handling**: Comprehensive exception handling for all HTTP error codes |
58 | | -- **Type Safety**: Full type hints support for better IDE experience |
59 | | -- **Context Manager**: Automatic resource cleanup |
| 72 | +### List Webhooks |
60 | 73 |
|
61 | | -### Coming Soon |
| 74 | +```python |
| 75 | +from tally import Tally |
62 | 76 |
|
63 | | -- **Forms Resource**: List, retrieve, and manage forms |
64 | | -- **Submissions Resource**: Access and filter form submissions |
65 | | -- **Webhooks Resource**: Manage webhooks and events |
66 | | -- **Organizations Resource**: Manage organization users and invites |
67 | | -- **Workspaces Resource**: List and manage workspaces |
| 77 | +client = Tally(api_key="tly_your_api_key_here") |
68 | 78 |
|
69 | | -## API Versioning |
| 79 | +# Get all webhooks |
| 80 | +for webhook in client.webhooks: |
| 81 | + print(f"{webhook.url} → enabled={webhook.is_enabled}") |
| 82 | +``` |
70 | 83 |
|
71 | | -The Tally API uses date-based versioning. You can specify a specific API version when initializing the client: |
| 84 | +### Create a Webhook |
72 | 85 |
|
73 | 86 | ```python |
74 | 87 | from tally import Tally |
75 | 88 |
|
76 | | -client = Tally( |
77 | | - api_key="tly-your-api-key-here", |
78 | | - api_version="2025-02-01" # Optional: specify API version |
| 89 | +client = Tally(api_key="tly_your_api_key_here") |
| 90 | + |
| 91 | +webhook = client.webhooks.create( |
| 92 | + url="https://your-app.com/webhooks/tally", |
| 93 | + event_types=["FORM_RESPONSE"], |
79 | 94 | ) |
| 95 | + |
| 96 | +print(f"Webhook created: {webhook.id}") |
80 | 97 | ``` |
81 | 98 |
|
82 | | -If not specified, the client will use the version tied to your API key. |
| 99 | +For complete API usage, visit the [📘 Webhooks Reference](https://pytally-sdk.fa.dev.br/api-reference/webhooks/). |
83 | 100 |
|
84 | | -## Error Handling |
| 101 | +--- |
85 | 102 |
|
86 | | -The SDK provides specific exceptions for different API errors: |
| 103 | +## Error Handling |
87 | 104 |
|
88 | 105 | ```python |
89 | | -from tally import Tally, UnauthorizedError, RateLimitError, TallyAPIError |
| 106 | +from tally import Tally, UnauthorizedError, NotFoundError |
90 | 107 |
|
91 | | -client = Tally(api_key="tly-your-api-key-here") |
| 108 | +client = Tally(api_key="tly_invalid") |
92 | 109 |
|
93 | 110 | try: |
94 | | - user = client.users.me() |
| 111 | + client.users.me() |
95 | 112 | except UnauthorizedError: |
96 | | - print("Invalid API key!") |
97 | | -except RateLimitError: |
98 | | - print("Rate limit exceeded. Please wait before retrying.") |
99 | | -except TallyAPIError as e: |
100 | | - print(f"API error: {e.message} (status code: {e.status_code})") |
| 113 | + print("Invalid API key.") |
| 114 | +except NotFoundError: |
| 115 | + print("Resource not found.") |
101 | 116 | ``` |
102 | 117 |
|
103 | | -## Configuration |
| 118 | +See [Error Handling → docs](https://pytally-sdk.fa.dev.br/error-handling/). |
104 | 119 |
|
105 | | -The client accepts the following configuration options: |
106 | | - |
107 | | -```python |
108 | | -from tally import Tally |
109 | | - |
110 | | -client = Tally( |
111 | | - api_key="tly-your-api-key-here", # Required: Your Tally API key |
112 | | - api_version="2025-02-01", # Optional: API version |
113 | | - timeout=30.0, # Optional: Request timeout in seconds |
114 | | - base_url="https://api.tally.so" # Optional: Custom base URL |
115 | | -) |
116 | | -``` |
| 120 | +--- |
117 | 121 |
|
118 | | -## Getting Your API Key |
| 122 | +## Documentation |
119 | 123 |
|
120 | | -1. Go to [Tally Settings > API Keys](https://tally.so/settings/api-keys) |
121 | | -2. Click "Create API key" |
122 | | -3. Copy and store your API key securely |
| 124 | +👉 Full documentation and API reference available at: |
| 125 | +**[https://pytally-sdk.fa.dev.br](https://pytally-sdk.fa.dev.br)** |
123 | 126 |
|
124 | | -> **Security Note**: Never commit your API key to version control. Use environment variables or a secure secrets manager. |
| 127 | +--- |
125 | 128 |
|
126 | 129 | ## Development |
127 | 130 |
|
128 | | -This project uses [uv](https://github.com/astral-sh/uv) for dependency management. |
| 131 | +Wanna help improve the SDK? |
129 | 132 |
|
130 | 133 | ```bash |
131 | | -# Clone the repository |
132 | 134 | git clone https://github.com/felipeadeildo/pytally.git |
133 | | - |
134 | | -# Install dependencies |
| 135 | +cd pytally |
135 | 136 | uv sync |
136 | | - |
137 | | -# Run tests (coming soon) |
138 | | -uv run pytest |
| 137 | +uv run mkdocs serve # preview docs locally |
| 138 | +pre-commit install # install pre-commit hooks |
139 | 139 | ``` |
140 | 140 |
|
141 | | -## Contributing |
142 | | - |
143 | | -Contributions are welcome! This SDK is in early development, and we'd love your help to: |
144 | | - |
145 | | -- Add missing API endpoints |
146 | | -- Improve documentation |
147 | | -- Report bugs |
148 | | -- Suggest new features |
149 | | - |
150 | | -Please feel free to open an issue or submit a pull request. |
151 | | - |
152 | | -## License |
153 | | - |
154 | | -This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details. |
| 141 | +--- |
155 | 142 |
|
156 | | -## Acknowledgments |
| 143 | +## 🔗 Links |
157 | 144 |
|
158 | | -This is an unofficial SDK and is not affiliated with or endorsed by Tally. Tally and the Tally logo are trademarks of Tally B.V. |
| 145 | +* 📦 [PyPI Package](https://pypi.org/project/pytally-sdk/) |
| 146 | +* 💻 [GitHub Repository](https://github.com/felipeadeildo/pytally) |
| 147 | +* 🧾 [Tally API Reference](https://developers.tally.so/api-reference/introduction) |
| 148 | +* 🪲 [Issue Tracker](https://github.com/felipeadeildo/pytally/issues) |
| 149 | +* 📘 [Documentation](https://pytally-sdk.fa.dev.br) |
159 | 150 |
|
160 | | -## Links |
| 151 | +--- |
161 | 152 |
|
162 | | -- [PyPI Package](https://pypi.org/project/pytally-sdk/) |
163 | | -- [GitHub Repository](https://github.com/felipeadeildo/pytally) |
164 | | -- [Tally API Documentation](https://tally.so/help/api) |
165 | | -- [Issue Tracker](https://github.com/felipeadeildo/pytally/issues) |
| 153 | +## ⚖️ License |
166 | 154 |
|
167 | | ---- |
| 155 | +Licensed under the [Apache License 2.0](https://github.com/felipeadeildo/pytally/blob/main/LICENSE). |
168 | 156 |
|
169 | | -Made with ❤️ by [Felipe Adeildo](https://github.com/felipeadeildo) |
| 157 | +> **Disclaimer** |
| 158 | +> This is an unofficial SDK and is not affiliated with or endorsed by Tally. |
| 159 | +> “Tally” and the Tally logo are trademarks of Tally B.V. |
0 commit comments