Flarebird

API reference

Everything you need to send notifications. Your URL is the only credential — keep it private and rotate it from the app if it leaks.

Quick start

The simplest possible request:

curl "https://flarebird.app/k7Qm2x9LpR4sTvWz8aBcDe/Build%20finished"

Send a notification

POST JSON to the push endpoint. Only title or body is required. POST /api/v1/push/{key}

curl -X POST "https://flarebird.app/api/v1/push/k7Qm2x9LpR4sTvWz8aBcDe" \
  -H "content-type: application/json" \
  -d '{"title":"Build finished","body":"All 84 tests passed in 42s","url":"https://github.com","group":"ci","level":"timeSensitive"}'

Fields

FieldTypeNotes
titlestringTitle or body is required. Up to 250 characters.
subtitlestringShown under the title. Up to 250 characters.
bodystringThe message. Alias: message. Shortened with … if it exceeds Apple's 4 KB limit.
urlhttps URLhttps:// only, up to 2048 characters. Opened when you tap the notification.
imagehttps URLhttps:// only. Downloaded on the device (max 10 MB, 5 s) and attached.
groupstringGroups notifications and history. Up to 64 characters.
soundenumdefault, aviso or none.
levelenumpassive, active (default) or timeSensitive. critical is not supported.
badgeintegerApp icon badge number (0–99999).
ttlintegerSeconds Apple keeps retrying if the phone is offline (default 86400, 0 = now or never).
copystringText copied by the "Copy" action. Defaults to the body.
collapsestringNotifications with the same value replace each other.

GET with query parameters

Same fields as query parameters. Perfect for browsers and Shortcuts.

curl "https://flarebird.app/api/v1/push/k7Qm2x9LpR4sTvWz8aBcDe?title=Build%20finished&body=All%2084%20tests%20passed%20in%2042s&group=ci"

URL shortcuts

Even shorter. Path segments are URL-decoded.

GET /{key}/{body}Body only
GET /{key}/{title}/{body}Title and body
POST /{key}POST text, JSON or a form
curl "https://flarebird.app/k7Qm2x9LpR4sTvWz8aBcDe/All%2084%20tests%20passed%20in%2042s"
echo "All 84 tests passed in 42s" | curl -X POST --data-binary @- "https://flarebird.app/k7Qm2x9LpR4sTvWz8aBcDe"

Responses

Successful requests return the APNs id. truncated is present when text had to be shortened.

{ "ok": true, "id": "8C6F1B7A-5B9E-4C1D-9F3A-2E7D6B0A1C44" }

Errors

Error messages follow your Accept-Language header (English or Spanish).

{ "ok": false, "error": { "code": "rate_limited", "message": "…" } }
CodeHTTPMeaning
invalid_key404Unknown or rotated URL
rate_limited429Too many requests — see Retry-After
invalid_payload400Validation failed — see fields
critical_not_supported400The critical level isn't available
device_gone410The iPhone is no longer registered
unavailable503Temporarily unavailable

Limits

Browsers & CORS

Push endpoints allow any origin, so you can call them from a web page.

Examples

curl "https://flarebird.app/k7Qm2x9LpR4sTvWz8aBcDe/Build%20finished/All%2084%20tests%20passed%20in%2042s"

# or with every option
curl -X POST "https://flarebird.app/k7Qm2x9LpR4sTvWz8aBcDe" \
  -H "content-type: application/json" \
  -d '{"title":"Build finished","body":"All 84 tests passed in 42s","url":"https://github.com","group":"ci"}'

Use Flarebird from your own projects

Store your URL in an environment variable called FLAREBIRD_URL and call it when something happens. The helper below never raises, so a failed ping can't break your script.

import json, os, urllib.request

FLAREBIRD_URL = os.environ.get("FLAREBIRD_URL", "https://flarebird.app/k7Qm2x9LpR4sTvWz8aBcDe")

def ping(title: str, body: str = "", **extra) -> bool:
    """Send a push to your iPhone. Never raises."""
    data = json.dumps({"title": title, "body": body, **extra}).encode()
    req = urllib.request.Request(FLAREBIRD_URL, data=data,
                                 headers={"content-type": "application/json"})
    try:
        with urllib.request.urlopen(req, timeout=10) as res:
            return res.status == 200
    except Exception:
        return False

ping("Build finished", "All 84 tests passed in 42s")