Push notifications

AI-written notifications

Create schedule rules whose notification is written fresh at every send from a short brief.

The brief

Set contentMode: "ai" on a schedule rule and send a brief instead of a title and body.

FieldRequiredLimitNotes
appDescriptionyes2,000 charactersWhat the app is and what to write about. Include every fact you want mentioned.
instructionsno2,000 charactersStanding rules: tone, topics to avoid, calls to action.
languageno60 charactersDefault "English".
examplesno10 examples, 300 characters eachStrings, or one string with one example per line. They set the voice and are never copied.

A weekly rule for a bookstore, saved paused so you can preview it first:

{
  "name": "Saturday story hour",
  "enabled": false,
  "contentMode": "ai",
  "appDescription": "Maple Street Books, a family bookstore. Invite families to Saturday story hour at 10:00 in the children's corner, and mention that new picture books arrive every week.",
  "instructions": "Warm and brief. No prices or discounts. Always say story hour starts at 10:00.",
  "language": "English",
  "examples": [
    "Story hour starts at 10 — bring the little ones!",
    "New picture books just arrived in the children's corner."
  ],
  "frequency": "weekly",
  "dayOfWeek": 5,
  "timeOfDay": "17:00",
  "timezone": "America/Chicago",
  "audienceKind": "all"
}

Send it to POST /api/apps/:appId/schedules, an account route like the rest of Scheduling; everything else works the same. An AI rule has title: null and body: null with its brief under ai, and each run records the copy that went out.

Preview a sample

POST https://app.nativenotify.com/api/apps/:appId/schedules/ai-sample

Writes one sample from a brief. Nothing is saved or sent. Send the brief fields, or the ruleId of an existing AI rule: its stored brief fills the fields you leave out, and its recent sends are the no-repeat history.

{
  "appDescription": "Maple Street Books, a family bookstore. Invite families to Saturday story hour at 10:00.",
  "instructions": "Warm and brief. No prices or discounts.",
  "language": "English"
}
{
  "ok": true,
  "sample": {
    "title": "Story hour this Saturday",
    "body": "Bring the family to the children's corner at 10:00 for stories and brand-new picture books."
  },
  "model": "~deepseek/deepseek-flash-latest",
  "attempts": 1
}

attempts is 2 when the retry was needed. Each sample is a real model call: 20 a minute and 300 a day per account user, and the daily count resets at midnight UTC.

Errors

StatusCodeMeaning
400bad_briefappDescription is missing, or a field is over its limit (field names it).
400bad_rule_idruleId isn't a positive integer.
404app_not_found, rule_not_foundThe app isn't one this account can access, or the rule isn't on it.
429limit_reachedThe per-minute or per-day sample limit is used up.
502llm_failed, invalid_outputThe model couldn't be reached, or returned no usable copy after the retry.
503llm_not_configuredAI writing isn't configured on the server.

As an MCP tool the sample is generate_ai_schedule_sample, and create_schedule_rule and update_schedule_rule take content_mode: "ai" with the brief fields.

What happens at each send

  1. The runner claims the occurrence, at most once.
  2. The model writes one title and body from the brief and the rule's 10 most recent sent notifications, so the wording varies.
  3. The copy is checked: a non-empty title of at most 65 characters and a non-empty body of at most 180 (an emoji counts once), with markup, markdown and wrapping quotes removed. A failed check gets one corrective retry.
  4. Usable copy is sent and saved on the run (title, body), which is the history step 2 reads next time.
  5. With no usable copy nothing is sent. The run is recorded failed with the reason, and the rule tries again at its next occurrence. There is never a blank or fallback push.

Writing rules

Whatever the brief says, notifications stay modest and fit for the whole family: nothing crude, suggestive, violent, hateful or mocking, and nothing about gambling, alcohol, drugs, tobacco, the occult or party culture. They use no fear, guilt or pressure, and invent no facts such as prices, discounts, dates, deadlines or promises the brief doesn't state. Each is plain text with one idea and at most one emoji. Your instructions apply unless they conflict with these rules.

Saving and editing

  • contentMode: "ai" needs appDescription (or a stored brief, on an update). A missing or oversized field is 400 bad_schedule, and the error's field names it.
  • title and body are ignored for an AI rule. Switching a fixed rule to AI clears them, so switching back needs them again. The brief stays stored.
  • PATCH changes only what you send: { "instructions": null } clears the instructions and { "examples": [] } clears the examples.