Python SDK
Careful: This package is coming soon and not published yet, so the install command below does not work today. Until it is, use the plain HTTP request from the quickstart.
One call from any Python server. Standard library only, Python 3.9 or newer.
Careful: Server-side only. Never put an API key in browser or mobile code.
Install
pip install pingloom
export PINGLOOM_API_KEY=<your key>
export PINGLOOM_BASE_URL=https://api.pingloom.devSet PINGLOOM_BASE_URL to the PingLoom API origin shown in your dashboard. The SDKs have no built-in default, so a key can never be sent to the wrong host by accident.
Send
send() returns the event ID. Only title is required. The limits are the same as the API reference: title 120 characters, body 2,000, data 8 KB.
from pingloom import PingLoom
pl = PingLoom() # reads PINGLOOM_API_KEY and PINGLOOM_BASE_URL
event_id = pl.send(
"Payment received: $49.00",
body="Order 1042 was paid.",
channel="payments",
priority="normal",
data={"order_id": "1042"},
action_url="https://example.com/orders/1042",
idempotency_key="order-1042-paid",
)Without idempotency_key the SDK generates a random one per call, so its own retries never create duplicates. Pass a key derived from the business event, like order-1042-paid, to make repeated calls of your own safe too.
Check the status
status() needs a key with the events:read scope.
event = pl.status(event_id)
print(event["status"]) # provider_accepted means FCM accepted itErrors and retries
Every API error becomes a typed exception with status, code, message, request_id and details. Retries default to 3, use exponential backoff or Retry-After, and always reuse the same idempotency key.
| API response | Exception | Retried automatically |
|---|---|---|
| 400, 413, 415, 422 | InvalidRequestError | No. Fix the request, see details. |
| 401 | AuthenticationError | No. The key is missing, revoked or invalid. |
| 403 | PermissionDeniedError | No. The key lacks the scope. |
| 404 | NotFoundError | No. |
| 409 | ConflictError | No. Same idempotency key with a different body. |
| 429 RATE_LIMITED | RateLimitError | Yes, after Retry-After. |
| 429 QUOTA_EXCEEDED | QuotaExceededError | No. The monthly quota is used. |
| 5xx | ServerError | Yes, with the same idempotency key. |
| No response | NetworkError | Yes. |
| Missing key or base URL | ConfigurationError | Not sent. |
from pingloom import PingLoom, QuotaExceededError, PingLoomError
try:
pl.send("Backup finished")
except QuotaExceededError:
... # the monthly quota is used; do not retry
except PingLoomError as e:
print(e.status, e.code, e.request_id) # the key is never in the messageThe key is masked in repr(), error text and logs as pl_live_****abcd.