Small helpers for sending notifications from your own backend in PHP, Node.js and Python. All three have the same methods and call the REST API for you, so anything in that guide can also be sent through them.
| PHP | Node.js | Python | |
|---|---|---|---|
| Folder | libraries/php | libraries/node | libraries/python |
| Needs | PHP 7.4+ with curl | Node.js 18+, no dependencies | Python 3.8+, standard library only |
| Error type | RuntimeException | PushixError | PushixError |
Use them only on your server. The REST API key can send to all your users, so never put it in an app or a web page.
Install
PHP — copy PushixClient.php into your project:
require __DIR__ . '/PushixClient.php';Node.js — install from the folder (it isn't on npm):
npm install /path/to/pushix/libraries/nodePython — install from the folder (it isn't on PyPI):
pip install /path/to/pushix/libraries/pythonCreate a client
Find the App ID and REST API key in the dashboard under App settings.
$push = new PushixClient('https://pushix.in', 'YOUR_APP_ID', getenv('PUSHIX_REST_API_KEY'));const { PushixClient, PushixError } = require('pushix-node'); // or: import { PushixClient } from 'pushix-node';
const push = new PushixClient('https://pushix.in', 'YOUR_APP_ID', process.env.PUSHIX_REST_API_KEY);from pushix import PushixClient, PushixError
push = PushixClient("https://pushix.in", "YOUR_APP_ID", os.environ["PUSHIX_REST_API_KEY"])Optional last argument: the timeout. PHP 15 (seconds), Node.js { timeoutMs: 15000 }, Python timeout=15.0.
Send to a user
Your own user ids are the ones you set with Pushix.login("10234") in the app or on the website. Every device of that user gets the message.
$res = $push->sendToUsers(['10234'], 'Order shipped', 'Your order #4821 is on the way');
echo $res['id'], ' ', $res['recipients'];const res = await push.sendToUsers(['10234'], 'Order shipped', 'Your order #4821 is on the way');
console.log(res.id, res.recipients);res = push.send_to_users(["10234"], "Order shipped", "Your order #4821 is on the way")
print(res["id"], res["recipients"])Pass '' as the title to send without one.
Send to a segment
$push->sendToSegments(['Active Users'], 'Diwali offer', 'Flash sale: 50% off today');
$push->sendToAll('Diwali offer', 'Flash sale: 50% off today'); // Subscribed Usersawait push.sendToSegments(['Active Users'], 'Diwali offer', 'Flash sale: 50% off today');
await push.sendToAll('Diwali offer', 'Flash sale: 50% off today');push.send_to_segments(["Active Users"], "Diwali offer", "Flash sale: 50% off today")
push.send_to_all("Diwali offer", "Flash sale: 50% off today")Built-in segments are listed in API.md. Filters work the same way with sendToFilters / send_to_filters.
Send with data and other fields
The fourth argument is data, delivered to your app or page as additionalData. The fifth, extra, is merged into the request last, so it can add any field from API.md or replace the generated ones.
$push->sendToUsers(['10234'], 'Order shipped', 'Your order #4821 is on the way',
['screen' => 'orders', 'id' => 'OD-4821'],
['isAnyWeb' => false, 'big_picture' => 'https://yourdomain.com/img/order.jpg', 'idempotency_key' => 'order-OD-4821']
);await push.sendToUsers(['10234'], 'Order shipped', 'Your order #4821 is on the way',
{ screen: 'orders', id: 'OD-4821' },
{ isAnyWeb: false, big_picture: 'https://yourdomain.com/img/order.jpg', idempotency_key: 'order-OD-4821' },
);push.send_to_users(["10234"], "Order shipped", "Your order #4821 is on the way",
{"screen": "orders", "id": "OD-4821"},
{"isAnyWeb": False, "big_picture": "https://yourdomain.com/img/order.jpg", "idempotency_key": "order-OD-4821"})idempotency_key makes retries safe: sending the same key again returns the first notification instead of sending twice.
For full control, send takes a whole payload (app_id is added for you):
$push->send(['include_external_user_ids' => ['10234'], 'contents' => ['en' => 'Hi', 'hi' => 'नमस्ते'], 'url' => 'myapp://orders']);await push.send({ include_external_user_ids: ['10234'], contents: { en: 'Hi', hi: 'नमस्ते' }, url: 'myapp://orders' });push.send({"include_external_user_ids": ["10234"], "contents": {"en": "Hi", "hi": "नमस्ते"}, "url": "myapp://orders"})Schedule
Add send_after. Strings like "2026-11-08 10:00:00 GMT+0530", ISO 8601 and unix seconds work everywhere; Node.js also takes a Date and Python a datetime (give it a time zone).
$res = $push->sendToAll('Diwali offer', 'Flash sale: 50% off today', [], ['send_after' => '2026-11-08 10:00:00 GMT+0530']);
$push->cancelNotification($res['id']); // changed your mindconst res = await push.sendToAll('Diwali offer', 'Flash sale: 50% off today', {}, { send_after: new Date('2026-11-08T10:00:00+05:30') });
await push.cancelNotification(res.id);from datetime import datetime, timedelta, timezone
ist = timezone(timedelta(hours=5, minutes=30))
res = push.send_to_all("Diwali offer", "Flash sale: 50% off today", extra={"send_after": datetime(2026, 11, 8, 10, 0, tzinfo=ist)})
push.cancel_notification(res["id"])Templates
Save the message once, then send it by id. Fields in the send replace the template's.
$tpl = $push->createTemplate('Order shipped', [
'headings' => ['en' => 'Order shipped'],
'contents' => ['en' => 'Hi {{ name | default: "there" }}, your order is on the way'],
]);
$push->sendTemplateToUsers($tpl['id'], ['10234'], ['data' => ['id' => 'OD-4821']]);
$list = $push->listTemplates();const tpl = await push.createTemplate('Order shipped', {
headings: { en: 'Order shipped' },
contents: { en: 'Hi {{ name | default: "there" }}, your order is on the way' },
});
await push.sendTemplateToUsers(tpl.id, ['10234'], { data: { id: 'OD-4821' } });
const list = await push.listTemplates();tpl = push.create_template("Order shipped", {
"headings": {"en": "Order shipped"},
"contents": {"en": "Hi {{ name | default: 'there' }}, your order is on the way"},
})
push.send_template_to_users(tpl["id"], ["10234"], {"data": {"id": "OD-4821"}})
templates = push.list_templates()Tags, users and stats
$push->setUserTags('10234', ['balance' => '250', 'old_tag' => '']); // '' deletes a tag
$n = $push->getNotification($res['id']); // status, successful, failed, converted …await push.setUserTags('10234', { balance: '250', old_tag: '' });
const n = await push.getNotification(res.id);
const user = await push.viewUser('10234'); // the user's devices and tags
const page = await push.listNotifications({ limit: 20 });push.set_user_tags("10234", {"balance": "250", "old_tag": ""})
n = push.get_notification(res["id"])
user = push.view_user("10234")
page = push.list_notifications(limit=20)viewUser and listNotifications are in the Node.js and Python libraries only; from PHP call GET /api/v1/apps/{app_id}/users/{id} and GET /api/v1/notifications directly.
Errors
A failed request throws. The message is Pushix: plus the server's first error. The HTTP status is in getCode() (PHP) or status (Node.js, Python); it is 0 when the server could not be reached or the request timed out (PHP also uses 0 when the answer wasn't JSON).
try {
$push->sendToUsers(['10234'], 'Hi', 'There');
} catch (RuntimeException $e) {
error_log($e->getCode() . ' ' . $e->getMessage()); // 403 Pushix: Access denied. The REST API key is not valid.
}try {
await push.sendToUsers(['10234'], 'Hi', 'There');
} catch (e) {
if (!(e instanceof PushixError)) throw e;
console.error(e.status, e.message, e.errors);
}try:
push.send_to_users(["10234"], "Hi", "There")
except PushixError as e:
print(e.status, e, e.errors)A send that matches nobody is not an error: the server answers HTTP 200 with recipients 0. Check it when it matters:
const r = await push.sendToUsers(['10234'], 'Hi', 'There');
if (r.recipients === 0) console.log(r.errors); // ["All included players are not subscribed"]The Node.js and Python libraries don't follow redirects (a redirect turns a POST into a GET). If you see HTTP 301 (redirect to https://…), use that address as the server URL.
Method names
| PHP / Node.js | Python | Request |
|---|---|---|
send(payload) | send(payload) | POST /api/v1/notifications |
sendToUsers(ids, title, message, data, extra) | send_to_users(...) | include_external_user_ids |
sendToSegments(segments, title, message, data, extra) | send_to_segments(...) | included_segments |
sendToAll(title, message, data, extra) | send_to_all(...) | included_segments: ["Subscribed Users"] |
sendToFilters(filters, title, message, data, extra) | send_to_filters(...) | filters |
sendTemplateToUsers(templateId, ids, override) | send_template_to_users(...) | template_id |
createTemplate(name, content) | create_template(...) | POST /api/v1/templates |
listTemplates() | list_templates() | GET /api/v1/templates |
getNotification(id) | get_notification(id) | GET /api/v1/notifications/{id} |
cancelNotification(id) | cancel_notification(id) | DELETE /api/v1/notifications/{id} |
setUserTags(userId, tags) | set_user_tags(...) | PUT /api/v1/apps/{app_id}/users/{id} |
listNotifications(options) (Node.js) | list_notifications(limit, offset, kind) | GET /api/v1/notifications |
viewUser(userId) (Node.js) | view_user(user_id) | GET /api/v1/apps/{app_id}/users/{id} |
More examples are in each folder's README.
Send your first notification
Create an app in Pushix to get your App ID and REST API key, then follow this guide. The free plan needs no card.