Bolrach Push API
Send a notification to a person, not to a token: target a user and Bolrach Push fans out to every device they have registered.
Quick start
Base URL: https://api.bolrach.io/push/v1
import { BolrachPush } from '@bolrach/push';
const push = new BolrachPush({ apiKey: process.env.BOLRACH_PUSH_KEY });
// One send reaches every device the person has registered.
const message = await push.send({
app_id: process.env.BOLRACH_PUSH_APP_ID,
target: { type: 'user', id: 'user_8123' },
title: 'Your order shipped',
body: 'Track it in the app.',
data: { order_id: '8123' },
priority: 1,
}, { idempotencyKey: 'order-8123-shipped' });
console.log(message.id, message.status);
import os
from bolrach_push import BolrachPush
push = BolrachPush(api_key=os.environ["BOLRACH_PUSH_KEY"])
message = push.send(
{
"app_id": os.environ["BOLRACH_PUSH_APP_ID"],
"target": {"type": "user", "id": "user_8123"},
"title": "Your order shipped",
"body": "Track it in the app.",
"data": {"order_id": "8123"},
"priority": 1,
},
idempotency_key="order-8123-shipped",
)
print(message["id"], message["status"])
Authentication
A server key (bt_live_…) from the API keys page of push.bolrach.io/console. Send it as a bearer token:
curl https://api.bolrach.io/push/v1/... \
-H "authorization: Bearer $YOUR_KEY"
SDKs
Official clients for Node and Python. Both retry on 429 and 5xx with exponential backoff,
obey Retry-After, accept idempotency keys on writes, and raise a typed
BolrachPushError carrying status, code, message
and requestId — so you branch on the failure instead of parsing a string.
npm install @bolrach/push
pip install bolrach-push
Every endpoint below lists its SDK method name. Anything not yet wrapped is still reachable without waiting for a release:
await client.request('GET', '/some/new/endpoint', { query: { days: 7 } }); // node
client.request('GET', '/some/new/endpoint', query={'days': 7}) # python
Errors and retries
Errors are JSON: {"error": {"code": "...", "message": "..."}}. The HTTP status
carries the category, the code carries the specific reason.
| STATUS | CODE | MEANING |
|---|---|---|
400 | bad_request | The body or a query parameter was missing or malformed. The message names the field. |
401 | unauthorized | No key, or a key this API does not recognise. |
403 | forbidden | A valid key without the scope this call needs, or a key not bound to the resource. |
404 | not_found | No such resource — or one that belongs to somebody else. The two are deliberately indistinguishable. |
409 | conflict | The same idempotency key was reused with a different body. |
429 | rate_limited | Too many calls. Retry after the seconds in the Retry-After header — the SDKs already do. |
5xx | server_error | Something failed on our side. Safe to retry; the SDKs retry twice with backoff. |
Idempotency-Key header. Reusing a key returns the original result rather than
applying the change twice — so a timeout you never saw the answer to is safe to repeat.Endpoints
Send a message. Pass idempotency_key to make a retry safe.
Idempotent. Pass an idempotency key and a retry returns the original result instead of applying the change twice.
await client.send({ /* body */ });
client.send({...})
Status of one message.
await client.getMessage(messageId);
client.get_message(message_id)
Every delivery attempt for one message, with provider outcomes.
await client.messageTrace(messageId);
client.message_trace(message_id)
Register a device. Returns the installation id, plus stream credentials when push_provider is "sse".
await client.registerInstallation({ /* body */ });
client.register_installation({...})
Map your own user id onto a Bolrach Push user.
await client.registerUser({ /* body */ });
client.register_user({...})
Report what happened on the device: delivered, displayed, opened.
await client.receipt({ /* body */ });
client.receipt({...})
Apps in this workspace.
await client.listApps();
client.list_apps()
Create an app.
await client.createApp({ /* body */ });
client.create_app({...})
One app.
await client.getApp(appId);
client.get_app(app_id)
Device counts and 24-hour send volume.
await client.appStats(appId);
client.app_stats(app_id)
Delivery insights: totals, daily series, and breakdowns by status, provider, platform and failure reason.
Query parameters: days.
await client.appInsights(appId);
client.app_insights(app_id)
Devices registered for an app.
await client.listInstallations(appId);
client.list_installations(app_id)
Recent deliveries for an app.
await client.listDeliveries(appId);
client.list_deliveries(app_id)
Webhook endpoints.
await client.listWebhooks();
client.list_webhooks()
Add a webhook endpoint.
await client.createWebhook({ /* body */ });
client.create_webhook({...})
Fire a signed test event at one endpoint and report what it answered - status, latency and body head.
await client.testWebhook(webhookId);
client.test_webhook(webhook_id)
Message templates.
await client.listTemplates();
client.list_templates()
Create a message template.
await client.createTemplate({ /* body */ });
client.create_template({...})