API Documentation

REST API for notifications via Telegram and Max. Subscribers, OTP, broadcasts, forms, helpdesk.

Forms

Public endpoint for receiving form submissions from websites. No API key required — safe for client-side JavaScript.

POST /f/{form_id}

body object required

Arbitrary JSON — any form fields

Request example

POST /f/{form_id}
 
{
"name": "John",
"email": "john@example.com",
"message": "I want to learn more"
}

Response

{
"ok": true
}

Form Fields

Any fields are accepted. Standard fields are highlighted in notifications and will be used in future integrations (CRM, Google Sheets).

name string

Sender name

email string

Sender email

phone string

Phone number

subject string

Subject

company string

Company

city string

City

url string

Website URL

message string

Message text

* any

Any other fields — passed as-is

allowed_origins format

Allowed origins are specified as domains. Scheme (http/https), www and slashes are normalized automatically — just write example.com and all variants (https://example.com, www.example.com, example.com/) will be accepted.

example.com — accepts submissions from https://example.com, http://example.com, https://www.example.com

*.example.com — any subdomain and example.com itself (requires at least second level, *.com is forbidden)

Local hosts (localhost, 127.0.0.1), private IPs and reserved TLDs (.local, .test, .example) are forbidden — the server returns an error on save

Security

Origin check — only allowed domains

Rate limit — 30 submissions/min per form

Honeypot — hidden _honey field to protect from bots

Sanitization — automatic HTML tag and dangerous content removal

Time-to-submit — minimum fill-time check. Default is 3 seconds (JS snippet sends `_submit_time` automatically). For plain HTML forms without JavaScript — set to 0 in form settings.

Blocklist of throwaway email services (mailinator, tempmail, …) — flagged as spam

Spam folder & filters

Spam submissions are NOT deleted — they go to a separate list for review. Webhooks and email notifications skip spam.

Spam tab in dashboard — separate list of flagged submissions

Honeypot — hidden field with a unique per-form name. If a bot fills it, the submission is silently rejected

Keyword blocklist — customizable word list. Matches are flagged as spam

Timestamp check — `_submit_time` set on page load, verified on submit (default 3 seconds). The JS snippet sends it automatically. For plain HTML forms without JS — disable the check (0) in form settings, otherwise submissions land in spam with reason 'missing_timestamp'.

Manually mark submissions as spam/not-spam in the dashboard

Submission Routes (Form Routes)

Unified model: route = trigger + action. Trigger — «always» (default recipient) or «conditional». Actions: deliver to recipient / mark as spam / block. Up to 40 routes per form.

Condition operators: `contains` (substring), `equals` (exact match). Condition field — field name or `*` for any string field

`mark_spam` — save, but flag as spam (no delivery, no webhook)

`block` — don't save at all (silent 200 OK)

`deliver` — deliver to recipient (email/messenger/subscriber/team). Conditional route adds to always-routes by default

Flag `replace_defaults` on a conditional deliver-route replaces all always-routes when matched — use for re-routing (e.g. «only sales submissions → sales@»)

Post-submit redirect

If `redirect_url` is set in form settings and the request came as `application/x-www-form-urlencoded` (HTML form, no JS), the server responds with `303 See Other` and `Location: <redirect_url>`. JSON requests (fetch/AJAX) still get `{ok:true}`.

Recipients: messengers (Telegram/Max), email, project subscribers

HTML form (no JavaScript)

The simplest integration path. The form works like a regular HTML submit — the browser POSTs to the endpoint. Protection: honeypot + filters. Set the Redirect URL in settings to show a thank-you page after submit.

<form action="https://api.zapnoty.com/f/form_abc123" method="POST">
<input type="text" name="name" required>
<input type="email" name="email" required>
<textarea name="message" required></textarea>
<input type="text" name="_hp_xxx" value="" style="display:none">
<button type="submit">Send</button>
</form>

Fetch / SPA

For single-page apps and dynamic forms. Returns `{ok:true}` JSON. Always handle `{ok:false, error}` and network errors. In the dashboard under «Integration Code → JavaScript» you get a constructor with flexible settings: 30-second timeout on the first attempt (Formspree-style), retry on 5xx/network, localStorage queue, and an idempotent `_request_id` — submissions survive short backend outages and aren't duplicated on retry.

async function submitForm(data) {
const res = await fetch('https://api.zapnoty.com/f/form_abc123', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
const json = await res.json();
if (!res.ok || !json.ok) throw new Error(json.error);
return json;
}

Related sections