VERNOfor developers

Verno developer API v1 — reference

Base: https://verno.co.in. All server calls: Authorization: Bearer vk_test_... or vk_live_.... Errors are {"detail": "<plain message>"} with the HTTP status below. Every key has scopes and a per-minute limit (429 + Retry-After when over it). A revoked key fails at once (401). A switched-off app's keys get 403.

Method + pathScopeBody / queryAnswer
GET /v1/meany—{app_id, mode, scopes}
GET /v1/users/{user_id}users.read—{user_id, scopes, name?, photo_url?} (name/photo only with profile)
POST /v1/bot/messagesbot.send{user_id, text} (≤1000){message_id, delivery}; 403 if the person never wrote in your app chat, said Stop or removed your app; 429 over 20 a day to one person
GET /v1/bot/threadsbot.readlimit{threads: [{user_id, started_chat, following, stopped, removed, last_message_at}]}
GET /v1/bot/threads/{user_id}/messagesbot.readlimit{messages: [{id, direction, body, created_at}]}
POST /v1/business-messagesmessages.send{user_id, template_id, params[]} or {user_id, text}{message_id, shown_from, delivery}; 403: not verified / not approved / template not approved / outside the 24 h window for text / person doesn't have, follow or chat with the app / stopped / paused by Verno; 400: wording or a link not allowed
POST /v1/business-messages/broadcastmessages.broadcast{template_id, params[]}{id, sent_to, skipped, queued}; followers only; 1 a day; big lists are sent in batches (queued: true)
POST /v1/paymentspayments.record{amount: "450.50", kind: upi_handoff | marked_paid, reference?, user_id?}{id, amount_paise, status: "recorded_not_verified"}
POST /v1/relationsrelations.write{user_id, kind: bill | booking, reference?}{id, status}: pending until the person confirms it in Vernolink; only then may you send them a first template
POST /v1/eventsevents.write{name: page_view | widget_tap | booking | order | form_reply | error | slow_page, target?, user_id?}{recorded}
POST /v1/webhooks/testwebhooks.test—{delivery_id} (a ping event)
POST /v1/oauth/tokennone (PKCE)form: grant_type=authorization_code, client_id, code, code_verifier, redirect_uri{access_token, token_type, expires_in: 3600, scope, user_id}; 400 invalid_grant
GET /v1/oauth/userinfoperson token vt_...—{user_id, scopes, name?, photo_url?}

Payments are records the business makes: customers pay the business directly by UPI. Verno never touches the money, and the dashboard labels them "recorded, not verified".

Webhook events

Common envelope: {"id": "whd_...", "event": "...", "mode": "test|live", "created": "<ISO time>", "data": {...}}.

Eventdata
message.received{user_id, message_id, text, first} — a person (or test user) wrote in your app chat
chat.opted_out / chat.opted_in{user_id} — Stop / Start in your app chat
app.installed{user_id, scopes}
app.uninstalled{user_id} — remove their access; tokens already stopped
user.delete_data{user_id, requested_at} — delete everything you hold about this person (DPDP)
ping{hello}

Headers: Verno-Event, Verno-Delivery (same on retries), Verno-Timestamp (Unix seconds), Verno-Signature: v1=HEX(HMAC-SHA256(secret, "<timestamp>.<raw body>")). Refuse timestamps older than 5 minutes.

Key scopes

users.read, bot.send, bot.read, messages.send, messages.broadcast, payments.record, events.write, webhooks.test. Person scopes (consent screen): profile, chat, location.

Limits

Per key: 1-600 requests a minute (default 60); every request counts, also the ones that fail. Bot replies: 20 per person per day. Broadcasts: 1 a day. Business message templates: 30 per app, up to 3 placeholders and 3 buttons (each opens a page of your own app).