Skip to main content

Official Python SDK for the SupportHub REST API

Project description

SupportHub Python SDK

Official Python SDK for the SupportHub REST API.

It provides ergonomic synchronous and asynchronous clients, fully typed pydantic v2 response models, and a high-level long-polling helper for real-time updates.

Installation

With Poetry:

poetry add supporthub-sdk

With pip:

pip install supporthub-sdk

Requires Python 3.10+.

Quick start

Synchronous

from supporthub import Client

with Client(api_key="sk_live_...") as client:
    page = client.tickets.list(status="open", page=1)
    for ticket in page.items:
        print(ticket.id, ticket.subject, ticket.status)

    ticket = client.tickets.create(
        contact={"email": "alice@example.com", "name": "Alice"},
        subject="Cannot log in",
        message="I get a 500 error when logging in.",
        priority="high",
    )

    client.messages.send(ticket_id=ticket.id, content="Thanks, looking into it!")
    client.tickets.close(ticket.id)

Asynchronous

import asyncio
from supporthub import AsyncClient

async def main():
    async with AsyncClient(api_key="sk_live_...") as client:
        page = await client.tickets.list(status="open")
        for t in page.items:
            print(t.id, t.subject)

asyncio.run(main())

Configuration

Client(
    api_key="sk_...",
    base_url="https://api.support.forestsnet.com/api/v1",  # optional
    timeout=30.0,                                           # optional
)

You can also inject your own httpx.Client / httpx.AsyncClient via http_client= if you need custom transports, proxies, retries, etc.

Resources

All clients expose the same resource attributes: client.tickets, client.messages, client.contacts, client.updates, client.webhooks.

Tickets

page    = client.tickets.list(status="open", priority="high", page=1, page_size=20)
detail  = client.tickets.get("ticket-uuid", last_messages=50)
ticket  = client.tickets.create(
    contact={"email": "user@example.com"},
    subject="Help",
    message="Initial message",
    priority="normal",
    tags=["billing"],
)
ticket  = client.tickets.update("ticket-uuid", status="resolved")
ticket  = client.tickets.close("ticket-uuid")
ticket  = client.tickets.reopen("ticket-uuid")

Messages

page = client.messages.list(ticket_id="ticket-uuid", page=1, page_size=50)
msg  = client.messages.send(ticket_id="ticket-uuid", content="Hello!", is_internal=False)

# Inbound from an external source (creates/finds contact and ticket automatically):
result = client.messages.create_inbound(
    contact={"email": "user@example.com", "name": "Alice"},
    message="Hi, I have a question",
    session_id="sess-abc",
)

Contacts

contacts = client.contacts.list(search="alice", page=1)
contact  = client.contacts.get("contact-uuid")
contact  = client.contacts.upsert(
    internal_id="user-123",
    full_name="Alice Smith",
    email="alice@example.com",
)

Updates (long polling)

Telegram-style long polling. The server holds the connection open until new events arrive or timeout seconds pass.

offset = 0
while True:
    updates = client.updates.poll(
        offset=offset,
        timeout=25,
        types=["ticket.created", "message.created"],
    )
    for u in updates:
        print(u.type, u.data)
        offset = max(offset, u.id)

The async client provides a higher-level streaming helper that tracks the offset internally and yields events as they arrive:

async with AsyncClient(api_key="sk_...") as client:
    async for update in client.updates.stream(types=["message.created"]):
        print(update.type, update.data)

Webhooks

webhooks = client.webhooks.list()
wh = client.webhooks.create(
    url="https://example.com/hooks/supporthub",
    events=["ticket.created", "message.created"],
    description="Production ingestion",
)
print(wh.secret)  # only returned once, on creation
client.webhooks.delete(wh.id)

Media

Upload, attach to a message, and download files:

# Upload (path, bytes, or file-like)
media = client.media.upload("./photo.jpg")

# Attach to an outbound message
client.messages.send(
    ticket_id=ticket.id,
    content="See attached",
    media_ids=[media.id],
)

# Download the raw bytes
blob = client.media.download(media.id)
with open("out.jpg", "wb") as f:
    f.write(blob)

Messages come back with a media array of MediaFile items:

detail = client.tickets.get(ticket.id)
for m in detail.messages:
    for mf in m.media:
        print(mf.id, mf.url, mf.mime_type, mf.file_type)

Ticket ratings

client.tickets.rate(ticket_id, 5, comment="Отлично!")

Long polling vs webhooks

  • Webhooks are best for production servers with a public HTTPS endpoint. SupportHub will POST events to your URL and sign them with your webhook secret.
  • Long polling (/updates) is great for development, prototyping, workers behind NAT, or any environment without a public callback URL. Use AsyncClient.updates.stream(...) for an async iterator that handles offset tracking and reconnection for you.

Error handling

All HTTP errors raise subclasses of supporthub.APIError:

Status Exception
400 ValidationError
401 AuthError
403 PermissionError
404 NotFoundError
422 ValidationError
429 RateLimitError
5xx ServerError

Each exception exposes:

  • .status_code — HTTP status
  • .error_code — backend error_code if present
  • .message — human-readable message
  • .detail — raw detail payload from the API
from supporthub import Client, RateLimitError, AuthError, APIError

try:
    client.tickets.list()
except AuthError:
    print("Bad API key")
except RateLimitError as e:
    print("Slow down, retry after", e.retry_after)
except APIError as e:
    print("API error:", e.status_code, e.message)

Models

All responses are parsed into pydantic v2 models with extra="allow" so unknown future fields will not break your code. Common types:

  • Ticket, TicketDetail, TicketStatus, TicketPriority
  • Message, SenderType
  • Contact
  • Update, UpdatesResponse
  • Webhook
  • PaginatedTickets, PaginatedMessages, PaginatedContacts

Use model.model_dump() to get a plain dict.

Development

cd sdks/python
poetry install
poetry run pytest
poetry run ruff check .

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

supporthub_sdk-0.4.0.tar.gz (11.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

supporthub_sdk-0.4.0-py3-none-any.whl (13.8 kB view details)

Uploaded Python 3

File details

Details for the file supporthub_sdk-0.4.0.tar.gz.

File metadata

  • Download URL: supporthub_sdk-0.4.0.tar.gz
  • Upload date:
  • Size: 11.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for supporthub_sdk-0.4.0.tar.gz
Algorithm Hash digest
SHA256 9f3ab795a242b579241e11092b79a9d8b8ab8d2f9cbad27018e5e01eb38907e1
MD5 b5499f73d8222621d7230bd2773f4d77
BLAKE2b-256 f0f76f0e7f32206bb030f98b93e817647bd0e6a32f1ed44dd45782ff4b37ccb7

See more details on using hashes here.

Provenance

The following attestation bundles were made for supporthub_sdk-0.4.0.tar.gz:

Publisher: publish-sdk.yml on forestsnet/saas-support

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file supporthub_sdk-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: supporthub_sdk-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 13.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for supporthub_sdk-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a761ee4b7daaf9eb61c9656939052dcc044dedc9a6256b9e3c510ea519ce9f08
MD5 1f35728e7d29939dce3a89ac753cb980
BLAKE2b-256 59513871030e2c4e3b3543a8ebc45d80badca28bb7d7cbb1a34692d1b77d8fe3

See more details on using hashes here.

Provenance

The following attestation bundles were made for supporthub_sdk-0.4.0-py3-none-any.whl:

Publisher: publish-sdk.yml on forestsnet/saas-support

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page