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.3.0.tar.gz (11.4 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.3.0-py3-none-any.whl (13.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: supporthub_sdk-0.3.0.tar.gz
  • Upload date:
  • Size: 11.4 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.3.0.tar.gz
Algorithm Hash digest
SHA256 92e499b6293161d256e7f0ba257cd4034f35b371788605c3cf6d2520c9e13737
MD5 32dc1101429d5cf607c1e16507b001a7
BLAKE2b-256 2e0691857e25164ad5afd71dd2193358378b20c69bf47aba45b804d7e0058240

See more details on using hashes here.

Provenance

The following attestation bundles were made for supporthub_sdk-0.3.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.3.0-py3-none-any.whl.

File metadata

  • Download URL: supporthub_sdk-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 13.1 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.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6d3191f4389b7670a3f7c4fccbfa97cf454fe373a2f63dddcf2a70503df102fa
MD5 d8e54fc4141946c4da4e71ca7ddf14db
BLAKE2b-256 ee15a151f1cd99a67fcf45516670a0c7613aefc07223e3e6b9d518b47a192797

See more details on using hashes here.

Provenance

The following attestation bundles were made for supporthub_sdk-0.3.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