Skip to content
DocumentationSign in

Webhooks

VERYO tells your server when a code is delivered and verified, so you do not need to poll the API. The endpoint, events and secret are set in the dashboard, in the Webhooks section. There you can also send a webhook.test test event and view the delivery log.

The endpoint must start with https:// and must not point to an internal network.

Events

Event When data fields
verification.delivered A channel delivered the code verification_id, phone, channel, cost_tiyn
verification.verified The user entered the correct code verification_id, phone, status
verification.failed Entry attempts or channels ran out verification_id, phone, status; reason, if delivery failed

correlation_id is added to data if it was passed in the request. No event is sent when a code expires.

{
  "id": "evt_1a2b3c4d5e6f70819a2b",
  "type": "verification.delivered",
  "created_at": "2026-11-08T10:00:03Z",
  "data": {
    "verification_id": "vrf_8c1f04a2b7d93e6f5a10",
    "phone": "+77011234567",
    "channel": "telegram",
    "cost_tiyn": 900,
    "correlation_id": "order-42"
  }
}

Signature verification

Header Value
X-Veryo-Event-Id Event identifier
X-Veryo-Timestamp Send time, Unix seconds
X-Veryo-Signature sha256= and the hex of HMAC-SHA256(secret, "<timestamp>.<raw body>")

The signature is computed over the raw request body, before JSON parsing:

import { createHmac, timingSafeEqual } from 'node:crypto'

function verify(rawBody, timestamp, signature, secret) {
  const hash = createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex')
  const expected = Buffer.from(`sha256=${hash}`)
  const got = Buffer.from(signature)
  return got.length === expected.length && timingSafeEqual(got, expected)
}

The secret is issued the first time you save the settings. When you rotate it in the dashboard, the old secret stops working immediately.

Response and retries

Respond with a 2xx code within 10 seconds. Redirects are not followed. After a failure, VERYO retries after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours and 15 hours, for 7 attempts in total.

Delivery is at-least-once: the same event may arrive twice. Discard duplicates by the event id.