Home/Guides/Send a push notification from PHP
Guide · PHP

How to send a push notification from PHP

Your PHP app already knows when something interesting happened — an order came in, a queue drained, a nightly job finished. Lert turns any of those moments into a push on your phone with a single HTTP POST. No API key, no SDK, no Composer package. This guide shows the cURL way, the zero-dependency way, and a reusable helper you can drop into any project.

What you need

Just your Lert endpoint URL. Open the app, and your unique URL is on screen — something like https://lert.dev/p/your-id. Tap Copy. Treat it like a password: anyone who has it can send you a notification, and you can regenerate it any time if it leaks. Everything below is plain PHP with no external dependencies.

Option 1: the cURL extension

The curl extension ships with nearly every PHP install and is the most direct way to make a request. Encode a small array as JSON, POST it to your URL, and you're done.

notify.php
<?php
$url = "https://lert.dev/p/your-id";
$payload = json_encode([
  "title" => "Order shipped",
  "body"  => "#1024 · Standard post",
  "tag"   => "orders",
]);

$ch = curl_init($url);
curl_setopt_array($ch, [
  CURLOPT_POST           => true,
  CURLOPT_HTTPHEADER     => ["Content-Type: application/json"],
  CURLOPT_POSTFIELDS     => $payload,
  CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $status === 200 ? "delivered\n" : "failed: $response\n";

A 200 response with {"delivered":1} means your phone is already buzzing. All three fields are optional — send just a body, or nothing at all, and Lert still delivers.

Option 2: file_get_contents, zero dependencies

If cURL isn't available — or you simply prefer core functions — a stream context does the same job. This is handy on locked-down hosts where installing extensions isn't an option.

notify-stream.php
<?php
$url = "https://lert.dev/p/your-id";
$payload = json_encode(["title" => "Backup complete", "body" => "42 GB · 3m 8s"]);

$context = stream_context_create([
  "http" => [
    "method"        => "POST",
    "header"        => "Content-Type: application/json\r\n",
    "content"       => $payload,
    "ignore_errors" => true,
  ],
]);

$response = file_get_contents($url, false, $context);
echo $response . "\n"; // {"delivered":1}

Setting ignore_errors to true lets you read the response body even on a non-200 status, so you can log a 404 (unknown endpoint) or 429 (rate limited) instead of getting a bare warning.

Prefer plain text? Send Content-Type: text/plain with the raw string as the body instead of JSON. Great for one-liners like a log message or a status string, and it sidesteps any JSON-escaping worries.

A reusable lert_notify() helper

Wrap it once and call it everywhere. This helper takes a title and body, returns true on success, and never throws — so a notification failure won't take down whatever your app was actually doing.

lert.php
<?php
function lert_notify(string $body, string $title = "", string $tag = ""): bool
{
    $url = getenv("LERT_URL") ?: "https://lert.dev/p/your-id";
    $data = array_filter(["title" => $title, "body" => $body, "tag" => $tag]);

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_HTTPHEADER     => ["Content-Type: application/json"],
        CURLOPT_POSTFIELDS     => json_encode($data),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 5,
    ]);
    curl_exec($ch);
    $ok = curl_getinfo($ch, CURLINFO_HTTP_CODE) === 200;
    curl_close($ch);
    return $ok;
}

// anywhere in your app:
lert_notify("New signup: ada@example.com", "🎉 New user", "signups");

Reading the URL from LERT_URL keeps your endpoint out of source control — set it in your environment or .env and the fallback is only there for a quick test. array_filter drops empty fields so you never send an empty title. Because it returns a bool instead of throwing, you can safely fire it from inside a request handler or a queued job.

Where to call it

  • Laravel: call lert_notify() from a queued job's handle(), or from a failed() method to hear about dead jobs.
  • WordPress: hook it to publish_post or WooCommerce's woocommerce_new_order to get a buzz on every sale.
  • Cron / CLI: drop the call at the end of a nightly script so you know it actually ran — see the cron guide.

Rate limits

Lert allows 60 requests per minute per IP, and the Free plan covers 50 notifications a day (Pro lifts that to unlimited, with a 10,000/day fair-use ceiling). If you exceed a limit you'll get a 429 with a Retry-After header — worth checking in a loop that could fire rapidly, so a runaway job doesn't spam you.

Why Lert for PHP notifications

Most notification services make you register an app, mint an API key, and pull in a client library before the first message goes out. Lert skips all of it: the endpoint URL is the authentication, so a notification is one curl_exec away. It's the fastest path from "my PHP app just did something" to "my phone told me about it."

FAQ

Do I need the cURL extension to send from PHP?

No. cURL is the most common choice, but file_get_contents with a stream context works too and ships with PHP core. Both send a plain HTTP POST, which is all Lert needs.

Do I need an API key or SDK?

No. Your Lert endpoint URL is the authentication — there's no separate key, token, or Composer package. Any PHP that can make an HTTP request can send a notification.

What should I send in the body?

Send JSON with optional title, body, and tag fields, or plain text with a text/plain content type. Title is capped at 120 characters and body at 2000.

Will this work from a Laravel or WordPress app?

Yes. It's a standard HTTP POST, so it runs from any PHP context — a Laravel job, a WordPress hook, a cron script, or a plain PHP file.

Your PHP app knows. Now your phone will too.

Download Lert, copy your URL, and drop lert_notify() into any project.

Get the app iOS