AyePingOpen app

API docs

Send a push notification to your phone with one web request.

Send a ping

POST https://ayeping.com/@username with your token in the Authorization header. /ping/@username works too, for tools that don't like an @ at the start of a path. Create tokens in the app, on the Tokens page.

Terminal
curl https://ayeping.com/@you \
  -H "Authorization: Bearer $AYEPING_TOKEN" \
  -d '{"title": "Backup finished",
       "message": "Saved **3 GB** to the NAS.",
       "label": {"text": "nas", "color": "green"}}'

A plain text body is the title, so the shortest ping is one line:

Terminal
curl https://ayeping.com/@you \
  -H "Authorization: Bearer $AYEPING_TOKEN" \
  -d "Deploy finished"

Body

JSON, up to 32 KB. A body that starts with { is read as JSON, so curl -d works without a Content-Type.

FieldRequiredRules
titleYes1–100 characters, one line.
messageNoUp to 2,000 characters. Markdown, see below.
label.textNo1–20 characters, shown as a chip.
label.colorNogray, red, orange, yellow, green, teal, blue, purple, pink. Defaults to gray.

Markdown

Messages support bold, italic, strikethrough, inline code, code blocks, lists, quotes, headings and links. A new line is a line break. Images aren't loaded (their alt text shows instead), so a message can't tell the sender when you read it. Links ask before they open.

More examples

JavaScript
await fetch("https://ayeping.com/@you", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.AYEPING_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    title: "Backup finished",
    message: "Saved **3 GB** to the NAS.",
  }),
});
Python
import json, os, urllib.request

request = urllib.request.Request(
    "https://ayeping.com/@you",
    data=json.dumps({"title": "Backup finished"}).encode(),
    headers={
        "Authorization": f"Bearer {os.environ['AYEPING_TOKEN']}",
        "Content-Type": "application/json",
    },
)
urllib.request.urlopen(request)

Responses

Errors are JSON with an error code: { "error": "rate_limited" }.

StatuserrorMeaning
202—Accepted. The body is the ping's id: { "id": "…" }.
400invalid_bodyThe body broke a rule below. message says which.
401unauthorizedMissing or wrong token, or the token isn't for this username.
402quota_exhaustedNo pings left. You also get one push about it a day.
403token_pausedThe token is paused. Resume it on the Tokens page.
413body_too_largeThe body is over 32 KB.
429rate_limitedOver the token's hourly limit, or too many requests from your IP. Wait Retry-After seconds.
429too_many_failed_attemptsToo many wrong tokens from your IP. Wait a minute.

Retries

Send an Idempotency-Key header (up to 255 characters) to retry safely. Another ping with the same key and token returns the first ping's id, and isn't delivered or counted again.

Terminal
curl https://ayeping.com/@you \
  -H "Authorization: Bearer $AYEPING_TOKEN" \
  -H "Idempotency-Key: nightly-backup-2026-10-21" \
  -d '{"title": "Backup finished"}'

Limits

  • Each token has an hourly limit, 1–3,600 (default 60). Accepted pings carry RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset headers.
  • Every ping uses one from your quota. Free accounts get 5 to try; Hobby and Pro get a monthly or yearly allowance (see pricing).
  • Pings are kept 90 days on Free and 365 days on Hobby and Pro.

Keeping tokens safe

A token can send pings to you, nothing else. Keep it in an environment variable or your CI's secrets, not in code. If one leaks, pause or delete it on the Tokens page; the others keep working.