Python client for the Green Relay SMS microservice API
Project description
green-relay (Python client)
A small, typed Python client for the Green Relay SMS microservice API. The
design follows the same shape as the OpenAI Python client: one GreenRelay
object configured with a base URL and API key, with endpoints grouped into
resource namespaces (messages, health, events).
Install
uv sync
The client uses requests for HTTP.
Quick start
from green_relay import GreenRelay
client = GreenRelay(api_key="your-key", base_url="http://localhost:8080")
# Queue a message (returns immediately, 202)
resp = client.messages.send(to="+14155552671", body="Hello")
print(resp.id, resp.status, resp.parts)
# Send and wait for the delivery outcome
result = client.messages.send_sync(to="+14155552671", body="Hello")
if result.queued:
print("still queued:", result.id)
else:
print("delivered:", result.status, result.reference)
# Look up an outbound message
msg = client.messages.get(resp.id)
print(msg.status, msg.error_code)
Reading messages: two ways
1. Synchronous
Poll inbound messages, or iterate the event stream directly:
# Polling
for inbound in client.messages.list_inbound(limit=50):
print(inbound.from_number, inbound.body)
# Blocking iterator over the live event stream
for event in client.events.stream():
print(event.name, event.data)
2. Callback / event listener
Run the stream in a background thread and dispatch to callbacks:
def on_sms(event):
print("inbound:", event.from_, event.body)
def on_status(event):
print("status:", event.id, event.status)
listener = client.events.listen(
on_inbound_sms=on_sms,
on_message_status=on_status,
)
# ... do other work ...
listener.stop()
Health and status
health = client.health.get() # works even when degraded/unhealthy
print(health.health, health.serial_connected)
status = client.health.status()
print(status.signal_percent, status.operator)
Error handling
Transport problems (connection refused, timeouts, DNS failures) propagate as
the standard requests
exceptions. Invalid arguments raise ValueError. A non-success HTTP response
raises a single APIError that mirrors the service's JSON error body (error
message + offending fields), with retry_after populated on 429/503.
import requests
from green_relay import APIError
try:
client.messages.send(to="bad", body="hi")
except APIError as exc:
print(exc.status_code, exc.error, exc.fields)
if exc.retry_after is not None:
print("retry after", exc.retry_after, "seconds")
except requests.RequestException as exc:
print("could not reach the server:", exc)
Logging
The library follows the standard convention: it attaches a NullHandler and
emits only DEBUG request logs under the green_relay logger. Configure
logging in your application to see them:
import logging
logging.basicConfig(level=logging.DEBUG)
Development
This project uses uv for dependency management
and ruff for linting and formatting. Run
everything from the python-client directory.
Install dependencies (including dev tools):
uv sync --all-groups
Lint, format, and test:
uv run ruff check . # lint
uv run ruff check --fix . # lint and auto-fix
uv run ruff format . # format
uv run ruff format --check . # verify formatting (used in CI)
uv run pytest # run the test suite
CI runs all of these on pushes and pull requests that touch python-client/
via .github/workflows/python-client.yml. See tests/README.md
for the test layout and examples/README.md for runnable
examples.
Releasing to PyPI
Publishing is automated by .github/workflows/python-client-publish.yml, which
builds the sdist and wheel with uv build and uploads them to PyPI using
Trusted Publishing (OIDC, no stored
API token).
One-time setup: on PyPI, add a trusted publisher for the green-relay project
pointing at this repository, the python-client-publish.yml workflow, and the
pypi environment.
To cut a release:
-
Bump the version in
pyproject.toml(uv version <new-version>updates it). -
Commit the bump.
-
Tag it with a
python-vprefix matching the version and push the tag:git tag python-v0.1.0 git push origin python-v0.1.0
The workflow verifies the tag matches the pyproject.toml version, re-runs the
lint/format/test checks, builds, and publishes. It can also be run manually via
the Actions tab (workflow_dispatch).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file green_relay-0.1.0.tar.gz.
File metadata
- Download URL: green_relay-0.1.0.tar.gz
- Upload date:
- Size: 38.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
690f013260f68a04338dc80e8d34b05dde6ae355109978da1763194618596800
|
|
| MD5 |
e74c3041b2d79a766adf99f47d1a0dfa
|
|
| BLAKE2b-256 |
dcbc831be0a05a0ffca690745ee90c2229605c113b1a6389be7955fd25a1a498
|
Provenance
The following attestation bundles were made for green_relay-0.1.0.tar.gz:
Publisher:
python-client-publish.yml on Greenstorm5417/green_relay
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
green_relay-0.1.0.tar.gz -
Subject digest:
690f013260f68a04338dc80e8d34b05dde6ae355109978da1763194618596800 - Sigstore transparency entry: 1866058086
- Sigstore integration time:
-
Permalink:
Greenstorm5417/green_relay@6f5c6cd68c57cabb18b6b5b34f25e1c4683e04ea -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Greenstorm5417
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-client-publish.yml@6f5c6cd68c57cabb18b6b5b34f25e1c4683e04ea -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file green_relay-0.1.0-py3-none-any.whl.
File metadata
- Download URL: green_relay-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96076745d3b1803b32def74e751285d4131fcfe8c2a53decbffeec63514361f7
|
|
| MD5 |
8c597c47d1ba8f5d81e4026067e160a4
|
|
| BLAKE2b-256 |
88ee4c0c59f8e5d7902ae751fb0f4cf0e0f5b8862fffacb29a66f170d57b383b
|
Provenance
The following attestation bundles were made for green_relay-0.1.0-py3-none-any.whl:
Publisher:
python-client-publish.yml on Greenstorm5417/green_relay
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
green_relay-0.1.0-py3-none-any.whl -
Subject digest:
96076745d3b1803b32def74e751285d4131fcfe8c2a53decbffeec63514361f7 - Sigstore transparency entry: 1866058189
- Sigstore integration time:
-
Permalink:
Greenstorm5417/green_relay@6f5c6cd68c57cabb18b6b5b34f25e1c4683e04ea -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Greenstorm5417
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-client-publish.yml@6f5c6cd68c57cabb18b6b5b34f25e1c4683e04ea -
Trigger Event:
workflow_dispatch
-
Statement type: