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.5.0.tar.gz (11.9 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.5.0-py3-none-any.whl (13.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: supporthub_sdk-0.5.0.tar.gz
  • Upload date:
  • Size: 11.9 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.5.0.tar.gz
Algorithm Hash digest
SHA256 52561a9695b2eb7232fe4d93643b18227b8fc92b1df470fe7590a69d659cbcee
MD5 5fc44ab00e717a8fa6df13a385a8f6f1
BLAKE2b-256 7eb6ceb006f673a4923148bbe7298bf35a33693c0698ca3c06217a49623fbd58

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: supporthub_sdk-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 13.9 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.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 aa2d76fdc444abb9d3dff773845950f59ea8b8495cdbf7928f52d17bd54ecfaf
MD5 aaa182e000d1278771ff086f46a2fb2d
BLAKE2b-256 7c32ce00cf803ae48105f6538f64a5ed604c655e487a951733f31fbaa856aa4f

See more details on using hashes here.

Provenance

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