Send notifications from your backend
Use this HTTP API when your own server should send a BNotify notification — for example after an order, a payment, or any event in your backend. The mobile SDK only registers the device and displays the message. Your server decides when to send.
Open BNotify Console → Settings. Use Webhooks as the request URL and API Key as apiToken in the JSON body. Do not hard-code another project’s key.
When to use this API
| You want to… | Use |
|---|---|
| Compose and send from the BNotify dashboard | Console campaigns (no code) |
| Send from your server when something happens in your product | This Backend API |
| Register a phone and show the notification | Android, iOS, or Flutter SDK |
Typical flow: the app SDK returns a device token → your app uploads that token to your server → your server POSTs this API with those tokens when it is time to notify.
Where to get the URL and API key
In the Console, open the project, then Settings.
| Console field | Use it as |
|---|---|
| Webhooks | The POST URL. Example shape: https://bnotify.convexinteractive.com/webhook. Always copy the value shown for your project. |
| API Key | The apiToken field inside the JSON body. This identifies the project. |
Call this endpoint only from your backend. Do not put the API key in a mobile app, a website frontend, or a public repository.
Endpoint
POST {Webhooks URL from Console → Settings}
Content-Type: application/json
The current production webhook is usually:
https://bnotify.convexinteractive.com/webhook
If Settings shows a different Webhooks value, use that value.
Request fields
Send one JSON object. apiToken and tokens are required for a targeted send. Include scheduledAt only when isScheduled is true.
| Field | Type | Required | Description |
|---|---|---|---|
apiToken | string | Yes | Project API Key from Console → Settings. |
tokens | string[] | Yes | Device tokens that should receive this notification. One string per device. |
title | string | Yes | Notification title. |
message | string | Yes | Notification body. |
type | string | No | Your label for the message, for example promo. |
screen | string | No | Screen name the app should open on tap. The SDK exposes this on the click callback. |
action | string | No | Action hint for the app, for example navigate. |
imageUrl | string | No | HTTPS image URL. iOS expanded images also need a Notification Service Extension. |
deepLink | string | No | Link the app can open, for example convexinteractive.com. |
isExpanded | string | No | "true" or "false". Controls expanded notification content. |
isScheduled | boolean | Yes | true to send later. false to send immediately. |
scheduledAt | string | Only if scheduled | Format YYYY-MM-DD HH:mm:ss, for example 2026-09-22 18:00:00. Omit this field when isScheduled is false. |
Send now vs schedule
Send immediately
Set isScheduled to false and do not send scheduledAt.
{
"title": "Order shipped",
"message": "Your order is on the way.",
"type": "promo",
"screen": "home",
"action": "navigate",
"imageUrl": "https://example.com/image.jpg",
"apiToken": "YOUR_API_KEY",
"isScheduled": false,
"isExpanded": "false",
"deepLink": "example.com",
"tokens": [
"DEVICE_TOKEN_1",
"DEVICE_TOKEN_2"
]
}
Send at a specific time
Set isScheduled to true and include scheduledAt.
{
"title": "Test Notification",
"message": "This is a test notification to check system",
"type": "promo",
"screen": "home",
"action": "navigate",
"imageUrl": "https://example.com/image.jpg",
"apiToken": "YOUR_API_KEY",
"isScheduled": true,
"isExpanded": "false",
"deepLink": "example.com",
"scheduledAt": "2026-09-22 18:00:00",
"tokens": [
"DEVICE_TOKEN_1"
]
}
Which devices receive it
tokens is the list of BNotify device tokens. The notification is sent only to those devices.
- Android / iOS / Flutter SDKs expose the token after registration (
onTokenin Flutter, the native token callback on Android and iOS). - Store that token on your server, next to the user account.
- When you notify one user, send that user’s token. When you notify many users, send every token in the same
tokensarray.
An empty tokens array does not identify a device. Always pass the tokens you collected from the SDK.
Examples
Replace YOUR_API_KEY with Settings → API Key, and replace device tokens with tokens from your database. The samples below send immediately (isScheduled: false, no scheduledAt).
cURL
curl --location 'https://bnotify.convexinteractive.com/webhook' \
--header 'Content-Type: application/json' \
--data '{
"title": "Test Notification",
"message": "This is a test notification to check system",
"type": "promo",
"screen": "home",
"action": "navigate",
"imageUrl": "https://example.com/image.jpg",
"apiToken": "YOUR_API_KEY",
"isScheduled": false,
"isExpanded": "false",
"deepLink": "example.com",
"tokens": [
"DEVICE_TOKEN_1"
]
}'
Node.js
const response = await fetch("https://bnotify.convexinteractive.com/webhook", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
title: "Test Notification",
message: "This is a test notification to check system",
type: "promo",
screen: "home",
action: "navigate",
imageUrl: "https://example.com/image.jpg",
apiToken: process.env.BNOTIFY_API_KEY,
isScheduled: false,
isExpanded: "false",
deepLink: "example.com",
tokens: ["DEVICE_TOKEN_1"],
}),
});
if (!response.ok) {
throw new Error(`BNotify webhook failed: ${response.status}`);
}
Python
import os
import requests
payload = {
"title": "Test Notification",
"message": "This is a test notification to check system",
"type": "promo",
"screen": "home",
"action": "navigate",
"imageUrl": "https://example.com/image.jpg",
"apiToken": os.environ["BNOTIFY_API_KEY"],
"isScheduled": False,
"isExpanded": "false",
"deepLink": "example.com",
"tokens": ["DEVICE_TOKEN_1"],
}
response = requests.post(
"https://bnotify.convexinteractive.com/webhook",
json=payload,
timeout=30,
)
response.raise_for_status()
PHP
$payload = [
"title" => "Test Notification",
"message" => "This is a test notification to check system",
"type" => "promo",
"screen" => "home",
"action" => "navigate",
"imageUrl" => "https://example.com/image.jpg",
"apiToken" => getenv("BNOTIFY_API_KEY"),
"isScheduled" => false,
"isExpanded" => "false",
"deepLink" => "example.com",
"tokens" => ["DEVICE_TOKEN_1"],
];
$ch = curl_init("https://bnotify.convexinteractive.com/webhook");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status < 200 || $status >= 300) {
throw new RuntimeException("BNotify webhook failed: " . $status);
}
Integration checklist
- 1Create the project and register the mobile app in the Console
- 2Integrate the Android, iOS, or Flutter SDK so devices produce a token
- 3Save each device token on your server
- 4Copy Webhooks and API Key from Console → Settings
- 5POST JSON from your backend with
apiTokenandtokens - 6For an immediate send, set
isScheduledtofalseand omitscheduledAt - 7For a later send, set
isScheduledtotrueand setscheduledAttoYYYY-MM-DD HH:mm:ss - 8Confirm the notification on a physical device that owns one of the tokens
Security
- Store the API key in a server secret (environment variable or secret manager), not in source control.
- Call the webhook only from your backend.
- Send tokens only for the users who should see that message.
- If an API key is exposed, generate a new one in the Console and update your server.
Set screen to the same route name your app reads from the SDK click callback (onClick / notification extras). The API delivers the payload; the app decides which screen to open.