Raley.one API Reference
Send OTP and transactional messages via Telegram in minutes. Designed for developers and AI agents.
Base URL
https://api.audiencetype.comAll requests must use HTTPS.
Quick Start — 5 Minutes
Get your first OTP delivered in 4 steps.
Create an API Key
Go to your Dashboard → API Keys → Create Key.
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"}'User receives code
The user receives a verification code on Telegram.
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.
Authentication
Include your API key in the Authorization header of every request. Find your key in Dashboard → API Keys.
Authorization: Bearer YOUR_API_KEY
Content-Type: application/jsonSend OTP · Telegram Bot
POST/v1/otp/sendSend 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
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
| to | string | Yes | Telegram chat ID of the recipient | "987654321" |
| channel | string | Yes | The name of your connected Telegram Bot channel (e.g. "telegram", "support") | "telegram" |
| language | string | No | OTP 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
Send OTP · Telegram Gateway
POST/v1/otp/sendSend 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?
| Feature | telegram_gateway | telegram bot |
|---|---|---|
| Setup required | None — managed by Raley.one | Requires a Telegram Bot token |
| Recipient field (to) | E.164 phone number | Telegram chat ID (numeric) |
| User requirement | None — works with any Telegram account | User must have started the bot first |
| Use case | OTP verification only | OTP + notifications + media |
| Price | More expensive (per message fee) | More economical |
Parameters
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
| to | string | Yes | E.164 phone number. Must start with + followed by country code. | "+18494634535" |
| channel | string | Yes | Must 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/verifyValidate 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
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
| to | string | Yes | Same recipient identifier used when sending the OTP | "+18494634535" |
| code | string | Yes | The 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/sendSend 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
| Field | Type | Required | Description |
|---|---|---|---|
| to | string | Yes | Telegram destination. Can be a User Chat ID, a Group Chat ID, a Channel Chat ID, or a Channel Username (e.g. "@relay_news") |
| channel | string | Yes | The name of your connected Telegram Bot channel (e.g. "telegram", "support") |
| type | string | Yes | Message type: text, image, video, document |
| content | string | Conditional | Message text or media caption. Required if type is text. |
| media | string | Conditional | URL to media file. Required for image, video, document types. |
| buttons | array | No | Array of interactive buttons (optional). Types: url, callback, contact. |
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/messagesRetrieve a paginated list of messages with optional filters.
Parameters
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
| limit | number | No | Number of messages (default 20, max 100) | 20 |
| cursor | string | No | Pagination cursor | "msg_01..." |
| to | string | No | Filter by recipient chat ID or phone number | "987654321" |
| channel | string | No | Filter by channel name | "telegram" |
| status | string | No | Filter by message status | "delivered" |
| direction | string | No | Filter 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/:idRetrieve 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/:idPermanently 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
EVENTTriggered 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
EVENTTriggered 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
EVENTTriggered when a user sends a message to your connected bot.
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
EVENTTriggered 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.
"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."
"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."
"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."
"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."
"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."