Website settings & more routes
GET and PUT /api/v1/settings for a website, plus the other API routes.
GET /api/v1/settings → { settings }. PUT /api/v1/settings (scope settings:write) merges the keys you send into the stored ones ({ "settings": { … } } or the keys at the top level) and answers { ok: true, settings }. The keys relaybell reads:
| Key | Meaning |
|---|---|
frequencyCap | Most pushes one browser gets in 24 hours; 0 or unset = no cap. Transactional sends skip it. |
quietHours | { enabled, start: "22:00", end: "08:00", timezone: "UTC" } — sends that would go out in this window wait until it ends. |
defaultUrl | The link used when a send has no url ("" or null removes it). |
utm | { enabled, source, medium, campaign } — added to notification links (source defaults to relaybell, medium to push). |
timezone | The website's time zone for reports, an IANA name (400 invalid_timezone). |
retentionDays | Delete activity history older than this many days: a whole number 0–3650, 0 = keep forever (400 invalid_retention_days). |
privacyUrl | Your privacy policy, linked from the opt-in prompt. |
conversionEvents, attributionWindowDays | Which events count as conversions, and how many days after a delivery a conversion is credited to it (default 7). See Events. |
report | { enabled, frequency: "weekly" | "monthly" } — the emailed performance report. POST /api/v1/reports/test sends one now. |
shopifySecret | Your Shopify webhook signing secret (see Shopify). |
identityVerification is shown here but changed only with PUT /api/v1/identity.
Other API routes
All of these take an API key (writes need the scope shown in scopes) and answer 404 not_found for an id that isn't one of this website's.
| Route | What it does |
|---|---|
/api/v1/feeds | RSS → push. POST { url, segmentId? } (400 invalid_url, 400 invalid_segment); PUT /:id { enabled?, segmentId? }; DELETE /:id. New posts in the feed are sent automatically; feeds are checked about every 15 minutes. |
/api/v1/schedules | Recurring campaigns. Body { name, content: { title, body, url, icon, segmentId | filters, topicId, excludeSegmentId | excludeFilters }, cadence, atTime, dayOfWeek, timezone, enabled }: cadence hourly · daily (default) · weekly; atTime "HH:MM" (default "09:00"); dayOfWeek 0–6, 0 = Sunday (default 1); timezone an IANA name (default UTC; 400 invalid_timezone). 400 content_title_required, 400 unknown_topic. |
/api/v1/templates | Saved notification copy: POST { name, content } (content is any object, e.g. a send body), PUT /:id, DELETE /:id. |
/api/v1/goals | Conversion goals: POST { name, eventName } (400 name_and_event_required; posting an existing name changes its event), PUT /:id, DELETE /:id; GET /api/v1/goals/stats?days=30 → { windowDays, funnel: { delivered, clicked }, goals }. |
/api/v1/onsite | On-site banners and slide-ins (shown by the SDK to every visitor): POST { title, body, ctaText, ctaUrl, style: "slidein" | "banner", active } (400 title_required), PUT /:id, DELETE /:id; GET includes impressions and clicks. |
PUT /api/v1/welcome | The welcome push for new subscribers: { "welcome": { enabled, title, body, url, icon, image } } — sent straight away to each new browser (it replaces the whole config). |
PUT /api/v1/logo | The default notification icon: { "logo": "https://…" } (null removes it). |
POST /api/v1/upload | Upload an image for a notification (scope send): multipart form field file, PNG, JPEG, GIF or WebP up to 2 MB → 201 { url }; anything else answers 400 invalid_file. 60 uploads an hour. |
POST /api/v1/ai/suggest | Copy suggestions. { title, body, goal? } → { ai, suggestions: [{ title, body }, …] }: three rewordings of your draft for you to edit — written by an AI model when ai is true, made from simple templates when it is false. 30 requests an hour. |