Raley.one API Reference

Send OTP and transactional messages via Telegram in minutes. Designed for developers and AI agents.

REST APIAI FriendlyNo Setup (Gateway)WebhooksNode.jsPython

Base URL

https://api.audiencetype.com

All requests must use HTTPS.

Quick Start — 5 Minutes

Get your first OTP delivered in 4 steps.

1

Create an API Key

Go to your Dashboard → API Keys → Create Key.

2

Send an OTP

Copy and run this command in your terminal for Telegram Gateway.

curl -X POST https://api.audiencetype.com/v1/otp/send \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to": "+18494634535", "channel": "telegram_gateway"}'

Or if you prefer to use a Telegram Bot:

curl -X POST https://api.audiencetype.com/v1/otp/send \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to": "987654321", "channel": "support"}'
3

User receives code

The user receives a verification code on Telegram.

4

Verify the code

Validate the code the user entered.

curl -X POST https://api.audiencetype.com/v1/otp/verify \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to": "+18494634535", "code": "123456"}'

How Raley.one Works

Your app never sees the raw OTP code. Everything is hashed and secured automatically.

🔢Generate OTP6-digit code
arrow_forward
🔒Hash codeSHA-256
arrow_forward
💾Store hashDatabase
arrow_forward
📨Send via TelegramGateway or Bot
arrow_forward
VerifyConstant-time
arrow_forward
🗑️Auto-expireCleanup

Authentication

Include your API key in the Authorization header of every request. Find your key in Dashboard → API Keys.

Required Headers
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

Send OTP · Telegram Bot

POST
/v1/otp/send

Send a one-time password to a Telegram chat ID. The user must have started your bot first (/start). The OTP code is generated automatically based on your workspace settings.

💡 Tip: Ask your users to open your Telegram bot and press Start during registration. Once done, they will receive OTPs automatically.

Parameters

FieldTypeRequiredDescriptionExample
tostringYesTelegram chat ID of the recipient"987654321"
channelstringYesThe name of your connected Telegram Bot channel (e.g. "telegram", "support")"telegram"
languagestringNoOTP message language (en, fr, es). Defaults to en."fr"

Example Request

curl -X POST https://api.audiencetype.com/v1/otp/send \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to": "987654321", "channel": "telegram", "language": "fr"}'

Success Response

{
  "success": true,
  "otpId": "otp_abc123",
  "expiresIn": 300,
  "channel": "telegram",
  "message": "OTP sent successfully"
}

Errors

lockTemporarily disabled

Send OTP · Telegram Gateway

POST
/v1/otp/send
Gateway

Send a native Telegram verification code to a phone number. No bot setup required — Raley.one handles everything.

🚀 No setup required: telegram_gateway is managed entirely by Raley.one. You do not need to create a Telegram Bot or connect any channel. Just send the request and it works.

Gateway vs Bot — When to use which?

Featuretelegram_gatewaytelegram bot
Setup requiredNone — managed by Raley.oneRequires a Telegram Bot token
Recipient field (to)E.164 phone numberTelegram chat ID (numeric)
User requirementNone — works with any Telegram accountUser must have started the bot first
Use caseOTP verification onlyOTP + notifications + media
PriceMore expensive (per message fee)More economical

Parameters

FieldTypeRequiredDescriptionExample
tostringYesE.164 phone number. Must start with + followed by country code."+18494634535"
channelstringYesMust be exactly "telegram_gateway""telegram_gateway"

Example Request

curl -X POST https://api.audiencetype.com/v1/otp/send \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to": "+18494634535", "channel": "telegram_gateway"}'

Success Response

{
  "success": true,
  "to": "+18494634535",
  "channel": "telegram_gateway",
  "expires_in": 300
}

Errors

Verify OTP

POST
/v1/otp/verify

Validate a code entered by the user. Raley.one compares the SHA-256 hash of the submitted code with the stored hash using constant-time comparison (immune to timing attacks).

💡 Tip: Once the user types the code into your app, call this endpoint. If the response says "verified": true, let them in!

Parameters

FieldTypeRequiredDescriptionExample
tostringYesSame recipient identifier used when sending the OTP"+18494634535"
codestringYesThe OTP code entered by the user"123456"

Example Request

curl -X POST https://api.audiencetype.com/v1/otp/verify \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to": "+18494634535", "code": "123456"}'

Success Response

{
  "success": true,
  "verified": true
}

Error Response

{
  "success": false,
  "error": {
    "code": "INVALID_OTP",
    "message": "The provided OTP is invalid or has expired."
  }
}

Errors

What Raley.one Does Automatically

You send one API call. Raley.one handles everything else.

Code Generation

Generates a secure random OTP code (default: 6 digits).

SHA-256 Hashing

The OTP code is never stored in plain text. Only the SHA-256 hash is saved in the database.

Auto Expiration

OTPs expire automatically after the configured time (default: 5 minutes).

Rate & Attempt Limits

Limits OTP sends (default: 5/hour) and max incorrect guesses (default: 5).

Resend Interval

Prevents spamming the same recipient (default: 60 seconds between sends).

Geo Filtering

Block or allow specific countries for OTP delivery.

Single Active OTP

Only one OTP is active per recipient. Sending a new one auto-expires the old one.

Timing-Safe Comparison

Verification uses crypto.timingSafeEqual() — immune to timing attacks.

Send Message

POST
/v1/messages/send

Send a transactional message (text, image, video, document) to a Telegram destination (User, Group, or Channel). Supports inline buttons and contact request buttons.

💡 Tip: Use this to instantly send a message (like a receipt, welcome message, alert, or an AI agent response) to a destination without generating an OTP. Works if the recipient has already started your Telegram bot, or if the bot is added to a group/channel. Note: To post in a channel, the bot must be an administrator with permission to post messages.

Parameters

FieldTypeRequiredDescription
tostringYesTelegram destination. Can be a User Chat ID, a Group Chat ID, a Channel Chat ID, or a Channel Username (e.g. "@relay_news")
channelstringYesThe name of your connected Telegram Bot channel (e.g. "telegram", "support")
typestringYesMessage type: text, image, video, document
contentstringConditionalMessage text or media caption. Required if type is text.
mediastringConditionalURL to media file. Required for image, video, document types.
buttonsarrayNoArray of interactive buttons (optional). Types: url, callback, contact.
Destination:
Buttons:

Example Request

curl -X POST https://api.audiencetype.com/v1/messages/send \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "to": "987654321",
  "channel": "telegram",
  "type": "text",
  "content": "Your order #1234 has been confirmed!"
}'

Success Response

{
  "success": true,
  "id": "msg_01KWNBGKNTTXZX8SX1",
  "status": "queued",
  "to": "987654321",
  "channel": "telegram",
  "type": "text",
  "content": "Your order #1234 has been confirmed!",
  "createdAt": "2026-07-03T15:00:00Z"
}

Errors

Get Messages List

GET
/v1/messages

Retrieve a paginated list of messages with optional filters.

Parameters

FieldTypeRequiredDescriptionExample
limitnumberNoNumber of messages (default 20, max 100)20
cursorstringNoPagination cursor"msg_01..."
tostringNoFilter by recipient chat ID or phone number"987654321"
channelstringNoFilter by channel name"telegram"
statusstringNoFilter by message status"delivered"
directionstringNoFilter by direction (inbound or outbound)"outbound"

Example Request

curl -X GET "https://api.audiencetype.com/v1/messages?limit=20&channel=telegram" \
  -H "Authorization: Bearer YOUR_API_KEY"

Success Response

{
  "success": true,
  "data": [
    {
      "id": "msg_01KWNBGKNTTXZX8SX9",
      "status": "delivered",
      "to": "987654321",
      "channel": "telegram",
      "type": "text",
      "content": "Your order #1234 has been confirmed!",
      "direction": "outbound",
      "createdAt": 1735702400000,
      "deliveredAt": 1735702402000
    }
  ],
  "pagination": {
    "count": 1,
    "next_cursor": null
  }
}

Get Message

GET
/v1/messages/:id

Retrieve the details and delivery status of a sent message.

Example Request

curl -X GET https://api.audiencetype.com/v1/messages/msg_01KWNBGKNTTXZX8SX9 \
  -H "Authorization: Bearer YOUR_API_KEY"

Success Response

{
  "success": true,
  "id": "msg_01KWNBGKNTTXZX8SX9",
  "status": "delivered",
  "to": "987654321",
  "channel": "telegram",
  "type": "text",
  "content": "Your order #1234 has been confirmed!",
  "createdAt": "2026-07-03T15:00:00Z"
}

Delete Message

DELETE
/v1/messages/:id

Permanently delete a message record from the system.

Example Request

curl -X DELETE https://api.audiencetype.com/v1/messages/msg_01KWNBGKNTTXZX8SX9 \
  -H "Authorization: Bearer YOUR_API_KEY"

Success Response

{
  "success": true,
  "id": "msg_01KWNBGKNTTXZX8SX9",
  "status": "deleted",
  "message": "Message has been successfully deleted."
}

Webhooks

Configure a webhook URL in Dashboard → Settings to receive real-time POST notifications.

💡 Tip: Webhooks let Raley.one notify your app automatically when events happen — no polling needed. Works great with Zapier, Make.com, or custom backends.

channel.connected

EVENT

Triggered when a messaging channel is connected to your workspace.

{
  "event": "channel.connected",
  "timestamp": "2026-07-03T10:00:00Z",
  "data": {
    "channel": "telegram",
    "accountId": "my_telegram_bot",
    "workspaceId": "wksp_123456"
  }
}

channel.disconnected

EVENT

Triggered when a channel is disconnected or encounters an authentication error.

The reason field can be: session_expired, session_logged_out, unknown

{
  "event": "channel.disconnected",
  "timestamp": "2026-07-03T12:30:00Z",
  "data": {
    "channel": "telegram",
    "accountId": "my_telegram_bot",
    "reason": "session_expired"
  }
}

message.received

EVENT

Triggered when a user sends a message to your connected bot.

The type field can be:

For media messages, the mediaUrl field contains a temporary download link. senderProfile contains the Telegram user's first name, last name, and username (if available).

{
  "event": "message.received",
  "timestamp": "2026-07-03T14:45:00Z",
  "data": {
    "messageId": "tg_987654",
    "channel": "telegram",
    "from": "123456789",
    "content": "Hello!",
    "type": "text",
    "senderProfile": {
      "firstName": "John",
      "lastName": "Doe",
      "username": "johndoe"
    }
  }
}

message.delivered

EVENT

Triggered when a message is successfully delivered to a recipient via your channel.

The type field can be: text, image, audio, video, document, poll, quiz, location, venue

{
  "event": "message.delivered",
  "timestamp": "2026-07-03T15:00:00Z",
  "data": {
    "messageId": "msg_01KWNBGKNTTXZX8SX9",
    "channelId": "ch_telegram123",
    "channel": "telegram",
    "to": "987654321",
    "content": "Your order #1234 has been confirmed!",
    "type": "text",
    "providerMessageId": "12345"
  }
}

Securing your Webhooks

To verify that a webhook request actually came from Raley.one and hasn't been tampered with, we include an HMAC SHA-256 signature in the x-signature header.

1. Get your webhook secret from your dashboard.

2. Calculate the HMAC SHA-256 hash of the raw JSON request body using your secret.

3. Compare your calculated hash with the value in the x-signature header.

Node.js Example

const crypto = require('crypto');

app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-signature'];
  const webhookSecret = process.env.WEBHOOK_SECRET;

  // 1. Calculate HMAC SHA-256 of the raw body
  const hmac = crypto.createHmac('sha256', webhookSecret);
  hmac.update(req.body);
  const calculatedSignature = hmac.digest('hex');

  // 2. Compare safely
  if (calculatedSignature !== signature) {
    return res.status(401).send('Unauthorized: Invalid signature');
  }

  // 3. Process the event
  const payload = JSON.parse(req.body.toString());
  console.log("Verified event:", payload.event);
  
  res.status(200).send('OK');
});

Security

Raley.one is built with security-first principles.

OTP codes hashed with SHA-256 — never stored in plain text

Telegram bot tokens encrypted using AES-256-GCM — never stored in plain text

HTTPS only — all API traffic is encrypted

Workspace isolation — data is separated per workspace

API key authentication on every request

Rate limiting to prevent abuse

Geographic filtering for Telegram Gateway OTP delivery

Automatic OTP expiration

One active OTP per recipient at any time

Constant-time hash comparison (prevents timing attacks)

Best Practices

Always use HTTPS

Never send API requests over plain HTTP.

Use environment variables

Never hardcode your API key. Use .env files or secrets managers.

Don't log OTP codes

Never print OTP codes in your application logs.

Never expose API keys client-side

Call the Raley.one API from your backend only, never from browser JavaScript.

Handle all error codes

Check the error.code field and display appropriate messages to your users.

Use with AI

Copy these prompts into your favorite AI coding tool to integrate Raley.one in seconds.

Cursor

"Create a Next.js API route that sends an OTP via Raley.one Telegram Gateway to a phone number, then verifies it. Use the endpoint POST https://api.audiencetype.com/v1/otp/send with { to, channel: 'telegram_gateway' } and POST /v1/otp/verify with { to, code }. Auth: Bearer token in header."

Claude Code

"Create an Express.js backend with two routes: POST /send-otp and POST /verify-otp. Use Raley.one API (base: https://api.audiencetype.com). Send OTP: POST /v1/otp/send { to, channel: 'telegram_gateway' }. Verify: POST /v1/otp/verify { to, code }. Use Bearer auth header."

ChatGPT

"Generate a Python FastAPI backend with two endpoints: /send-otp and /verify-otp. Use the Raley.one API at https://api.audiencetype.com. POST /v1/otp/send with body { to: phone_number, channel: 'telegram_gateway' }. POST /v1/otp/verify with { to, code }. Include Bearer token auth."

Windsurf

"Build a complete user authentication flow using Raley.one OTP API. Base URL: https://api.audiencetype.com. Steps: 1) User enters phone number 2) POST /v1/otp/send { to, channel: 'telegram_gateway' } 3) User enters code 4) POST /v1/otp/verify { to, code }. Handle all errors."

GitHub Copilot

"Create a Django REST view that integrates Raley.one OTP verification. Use requests library. POST https://api.audiencetype.com/v1/otp/send with { to: phone, channel: 'telegram_gateway' }. POST /v1/otp/verify with { to, code }. Bearer token in Authorization header."