Zapnoty — Approvals — one-tap confirmations

API Documentation

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

Approvals

Interactive confirmations via a Telegram/Max bot: a question with buttons, follow-up on click, notification routes and webhooks — without your own backend for the buttons.

How it works

First you create a template (scenario) — a question with {{vars}}, a set of buttons, follow-up texts and routes per outcome. Then you launch a specific approval for a subscriber from that template — immediately or at a scheduled time. The bot sends the question with buttons, and on click sends its follow-up text, applies notification routes and fires a webhook. No backend of your own is needed to handle the buttons.

Endpoints

POST /v1/approval-templates — create a template (scenario)
POST /v1/approval-templates/{id}/routes — notification route per outcome
POST /v1/approvals — launch an approval
GET /v1/approvals/{id} — status and outcome
POST /v1/approvals/{id}/cancel — cancel (while unanswered)

1. Creating a template

A template defines the prompt question (text, optional format and media) with {{vars}} placeholders, the buttons and the follow-up texts for each outcome. Only the approve button is required; decline and reschedule are optional. default_ttl_minutes is the default time-to-live unless overridden at launch.

POST /v1/approval-templates
Authorization: Bearer zn_live_...
{
"prompt": { "text": "Doctor appointment at {{time}}. Coming?" },
"buttons": {
"approve": { "label": "I'll come" },
"decline": { "label": "Can't make it" },
"reschedule": { "label": "Reschedule" }
},
"follow_up": {
"approved": "Thanks! See you at {{time}}.",
"declined": "The booking is cancelled.",
"reschedule": "Our staff will reach out.",
"expired": "No reply — we'll remind you later."
},
"default_ttl_minutes": 1440
}

Buttons and outcomes

approve object required

Confirm button — approved outcome. { label }

decline object

Decline button — declined outcome. Optional

reschedule object

Reschedule button — reschedule outcome. Optional

expired

Outcome when TTL expires without an answer (no button — only follow-up and route)

2. Routes per outcome

Just like in forms: a route links an outcome (trigger_outcome: approved | declined | reschedule | expired) to a recipient (recipient_type: email | messenger | subscriber | team). For example, on declined notify the reception by email.

POST /v1/approval-templates/{template_id}/routes
Authorization: Bearer zn_live_...
{
"trigger_outcome": "declined",
"recipient_type": "email",
"recipient_email": "reception@clinic.ru"
}

3. Launching an approval

A launch creates a specific approval from a template. Identify the subscriber via subscriber_id or external_id (your own user identifier). scheduled_at sends it at a set time instead of immediately. vars are substituted into the {{placeholders}} of the question and follow-up.

POST /v1/approvals
Authorization: Bearer zn_live_...
{
"template_id": "aptpl_abc123",
"subscriber_id": "sub_2aUyqjCzEIiEcYMKj7TZtw",
"scheduled_at": "2026-07-02T09:00:00Z",
"ttl_minutes": 180,
"vars": { "time": "18:00" },
"metadata": { "booking_id": "bk_991" }
}

Launch parameters

template_id string required

Approval template ID

subscriber_id string

Subscriber ID (or external_id)

external_id string

Your own user identifier (or subscriber_id)

scheduled_at string

ISO-8601 — send time. Omitted → immediately

ttl_minutes integer

Time-to-live, overrides the template default_ttl_minutes

vars object

Values for the {{placeholders}} in the question and follow-up

metadata object

Arbitrary data — returned in the webhook and status

Response

{
"id": "apr_8kQ2mzT1",
"status": "scheduled",
"outcome": null
}

4. Status and outcome

Poll the approval status by its ID. status goes sent → answered (or expired / cancelled). outcome appears after the reply: approved, declined or reschedule.

GET /v1/approvals/apr_8kQ2mzT1
Authorization: Bearer zn_live_...
{
"id": "apr_8kQ2mzT1",
"status": "answered",
"outcome": "approved",
"answered_at": "2026-07-02T15:03:11Z"
}

5. Webhook events

Zapnoty fires a webhook at every step: approval.sent (question sent), approval.approved, approval.declined, approval.reschedule (subscriber reply) and approval.expired (TTL elapsed). Signed with X-Zapnoty-Signature (HMAC-SHA256), like all other events.

POST https://your-app.com/webhooks
X-Zapnoty-Signature: sha256=...
{
"event": "approval.approved",
"approval_id": "apr_8kQ2mzT1",
"template_id": "aptpl_abc123",
"outcome": "approved",
"external_id": "bk_991",
"answered_at": "2026-07-02T15:03:11Z"
}

Billing

Sending the question to a subscriber — 1 credit
Follow-up after the reply — 1 credit
Email notification route — 3 credits

Related sections