Skip to main content

Python SDK for Bulletins

Project description

bulletins

Python SDK for the Bulletins API. Async client, SSE streaming, and a declarative bot framework.

Install

uv add bulletins-sdk

Quick start

Client

import asyncio
from bulletins import BulletinsClient

async def main():
    client = BulletinsClient("bk_...", base_url="https://bulletins.no")

    async with client:
        await client.resolve()  # auto-resolves party + integration from key
        threads = await client.list_threads()
        for t in threads:
            print(f"{t.name} ({t.status})")

        await client.send_message(threads[0].id, "Hello from Python")

asyncio.run(main())

SSE streaming

async with client.stream_party() as stream:
    async for event in stream:
        print(f"[{event['type']}] {event.get('senderName')}: {event['content']}")

Bot

Declarative bot with auto-registration of event types and actions:

import asyncio
from bulletins import Bot, EventTypeSpec, ActionSpec

bot = Bot(
    "Ping Bot",
    event_types=[
        EventTypeSpec("bot:pong",
            content_schema={"message": {"type": "string"}},
            display_hint={"label": "Pong"}),
    ],
    actions=[
        ActionSpec("Approve", color="success"),
        ActionSpec("Reject", color="destructive"),
    ],
)

@bot.on("message")
async def handle(event, client):
    body = (event.content or {}).get("body", "")
    if body.startswith("!ping"):
        await client.send_message(event.thread_id, "pong")

@bot.on("action_invoked")
async def on_action(event, client):
    key = (event.content or {}).get("key", "")
    match key:
        case "Approve": ...
        case "Reject": ...

asyncio.run(bot.start(api_key="bk_...", base_url="https://bulletins.no"))

Create the integration and API key in the Bulletins settings UI. The bot auto-resolves its party and integration from the API key, registers event types and actions on startup, and dispatches incoming events to handlers.

Action IDs are available via bot.action_ids after start — pass them to create_event to attach inline controls:

await client.create_event(thread_id, "bot:pong", {"message": "pong"},
    actions=[bot.action_ids["Approve"], bot.action_ids["Reject"]])

API

BulletinsClient

Method Description
resolve() Auto-resolve party + integration from API key
list_threads() List threads for the active party
get_thread(id) Thread detail with events and participants
create_thread(name, to_party_id, body) Create a thread with initial message
list_events(thread_id, before, limit) Paginated event history
create_event(thread_id, type, content, actions) Create any event type, optionally with inline action IDs
send_message(thread_id, body) Send a text message
stream_party() SSE stream for all party events
stream_thread(thread_id) SSE stream for a single thread
list_integrations() List integrations
get_integration_detail(id) Integration with all child resources
create_event_type(integration_id, ...) Register a custom event type
create_action(integration_id, ...) Create an action
create_webhook(integration_id, ...) Create a webhook
create_api_key(integration_id, ...) Create an API key
get_agent_token(thread_id) LiveKit token for joining calls

Bot

Method Description
on(event_type) Decorator to register an event handler
start(api_key, base_url) Resolve identity, register event types + actions, dispatch loop
stop() Stop the dispatch loop
action_ids dict[str, str] — action name to UUID, populated after start

ActionSpec

Field Type Description
name str Action button label
method str "event" (default) or "POST"
color str | None Semantic token: "destructive", "success", or "warning"
requested_schema dict | None JSON Schema for form/slider input
url_template str | None URL template for POST/link actions

EventTypeSpec

Field Type Description
name str Namespaced type, e.g. "bot:now_playing"
content_schema dict JSON Schema for event content validation
display_hint dict | None {"label": "Human-readable name"}

Requirements

Python 3.12+, httpx.

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

bulletins_sdk-0.3.0.tar.gz (7.9 kB view details)

Uploaded Source

Built Distribution

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

bulletins_sdk-0.3.0-py3-none-any.whl (10.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: bulletins_sdk-0.3.0.tar.gz
  • Upload date:
  • Size: 7.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.13 {"installer":{"name":"uv","version":"0.11.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"EndeavourOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for bulletins_sdk-0.3.0.tar.gz
Algorithm Hash digest
SHA256 f46fb25c11f585d11e9423a298d857e73f83b0f66a7ec6076d1c407d7621b1b8
MD5 ab3309d1769efac269b7ef66e76e581f
BLAKE2b-256 58f7f52419fd552ac21f8954cd2025ee96a30ca26e9f9c959e2ae7b47cf19959

See more details on using hashes here.

File details

Details for the file bulletins_sdk-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: bulletins_sdk-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 10.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.13 {"installer":{"name":"uv","version":"0.11.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"EndeavourOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for bulletins_sdk-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f1f8257d59ab697caccde12f4c0f316d42164a2eb9e92509724df1c9a7b3bf5f
MD5 6ada3e03bba088a3cc0333e0edfbe9ec
BLAKE2b-256 d2254584137081e175b5b8dd3d88ae30eaeeabb1c0ff5ae8eace4ed72d25a383

See more details on using hashes here.

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