Skip to content

PyTally SDK

Unofficial Python SDK for the Tally.so API.

PyPI version Python Versions License

Introduction

PyTally SDK is a Python library that provides a simple and intuitive interface to interact with the Tally.so API. It handles authentication, request/response processing, pagination, and error handling, allowing you to focus on building your application.

What's Implemented

Currently, the SDK covers the following Tally API resources:

  • Users - Get current user information
  • Organizations - Manage users and invites
  • Forms - Create, update, and manage forms and submissions
  • Workspaces - List and manage workspaces
  • Webhooks - Configure and monitor webhook integrations
  • 🚧 MCP - Not implemented yet

Official API Documentation

For complete API details and specifications, refer to the Official Tally API Documentation.

Installation

Using pip

pip install pytally-sdk

Using uv

uv is a fast Python package installer and resolver:

uv add pytally-sdk

Requirements

  • Python 3.11 or higher
  • httpx library (automatically installed)

Quickstart

Get started with PyTally SDK in just a few lines of code:

Basic Usage

from tally import SUPPORTED_TALLY_API_VERSION, Tally

# Initialize the client with your API key
client = Tally(
    api_key="tly_your_api_key_here",
    api_version=SUPPORTED_TALLY_API_VERSION,
)

# Get current user information
user = client.users.me()
print(f"Hello, {user.full_name}!")
print(f"Email: {user.email}")
if user.subscription_plan:
    print(f"Plan: {user.subscription_plan.value}")

Using Context Manager

The recommended approach for automatic resource cleanup:

from tally import SUPPORTED_TALLY_API_VERSION, Tally

with Tally(
    api_key="tly_your_api_key_here",
    api_version=SUPPORTED_TALLY_API_VERSION,
) as client:
    # Get current user
    user = client.users.me()
    print(f"Organization ID: {user.organization_id}")

    # List all forms
    for form in client.forms:
        print(f"Form: {form.name} (ID: {form.id})")

Working with Forms

from tally import SUPPORTED_TALLY_API_VERSION, Tally

client = Tally(
    api_key="tly_your_api_key_here",
    api_version=SUPPORTED_TALLY_API_VERSION,
)

# List forms with pagination
forms = client.forms.all(page=1, limit=10)
print(f"Found {len(forms.items)} forms")

# Get a specific form
form = client.forms.get(form_id="wXYz123")
print(f"Form: {form.name}")
print(f"Status: {form.status.value}")
print(f"Submissions: {form.number_of_submissions}")

# List form submissions
submissions = client.forms.list_submissions(
    form_id="wXYz123",
    filter="all",
    page=1,
)

for submission in submissions.submissions:
    print(f"Submission ID: {submission.id}")
    print(f"Submitted: {submission.submitted_at}")

Setting up Webhooks

from tally import SUPPORTED_TALLY_API_VERSION, Tally

client = Tally(
    api_key="tly_your_api_key_here",
    api_version=SUPPORTED_TALLY_API_VERSION,
)

# Create a webhook
webhook = client.webhooks.create(
    form_id="wXYz123",
    url="https://your-app.com/webhooks/tally",
    event_types=["FORM_RESPONSE"],
)

print(f"Webhook created: {webhook.id}")

# List webhook events
events = client.webhooks.get_events(webhook_id=webhook.id)
for event in events.events:
    print(f"Event: {event.event_type.value} - {event.delivery_status.value}")

API Versioning

The Tally API uses date-based versioning. You can specify a specific API version when initializing the client:

from tally import SUPPORTED_TALLY_API_VERSION, Tally

client = Tally(
    api_key="tly_your_api_key_here",
    api_version=SUPPORTED_TALLY_API_VERSION,
)

The SDK is validated against 2025-05-30 and uses that version by default.

Error Handling

The SDK provides specific exceptions for different error scenarios:

from tally import Tally, UnauthorizedError, RateLimitError, NotFoundError

client = Tally(api_key="tly_your_api_key_here")

try:
    form = client.forms.get(form_id="invalid_id")
except UnauthorizedError:
    print("Invalid API key!")
except NotFoundError:
    print("Form not found!")
except RateLimitError as e:
    print(f"Rate limit exceeded. Try again later.")
    print(f"Status code: {e.status_code}")

For more details, see the Error Handling guide.

Configuration Options

The TallyClient accepts the following configuration options:

from tally import SUPPORTED_TALLY_API_VERSION, Tally

client = Tally(
    api_key="tly_your_api_key_here",       # Required: Your Tally API key
    api_version=SUPPORTED_TALLY_API_VERSION,  # Optional: defaults to the SDK compatibility target
    timeout=30.0,                          # Optional: Request timeout in seconds (default: 30.0)
    base_url="https://api.tally.so",       # Optional: Custom base URL (default: https://api.tally.so)
)

Testing

The project includes two test layers:

  • Unit tests for TallyClient and forms serialization/parsing
  • Live read-only API tests for listing forms and form submissions
PYTHONPATH=src python -m pytest tests/test_client.py tests/resources/test_forms.py
export TALLY_API_KEY="tly_your_api_key_here"
export TALLY_FORM_ID="your_form_id"
export TALLY_API_VERSION="2025-05-30"
PYTHONPATH=src python -m pytest -m live_api tests/integration/test_forms_live.py

Next Steps

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Disclaimer

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.