Rasayel Platform

Start building
with Rasayel

One API for every conversation: send and receive on WhatsApp, email, Telegram, web chat and your own channels. From first call to production.

Send a WhatsApp message
curl -X POST https://rasayel.net/api/v1/messages \
  -H "Authorization: Bearer $RASAYEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channelId": "ch_01J9Z3",
    "to": "+201001234567",
    "text": "Hello from Rasayel 👋"
  }'

Platform

Choose how you build

Pick the way your system talks to Rasayel. Most integrations use the first two together.

Developer journey

From idea to production

Follow the steps, or jump to what you need.
  1. 1
  2. 2
  3. 3

Get started

Quickstart

  1. An owner or admin creates a key under Settings → API. It is shown once.
  2. List your channels to find the channelId to send from.
  3. Send a message to any number. The reply arrives at your event webhook.

Get started

Authentication

Send the key as a bearer token on every request. Keys belong to one organization and only ever see its data. Base URL: https://rasayel.net/api/v1
1. List channels
curl https://rasayel.net/api/v1/channels \
  -H "Authorization: Bearer $RASAYEL_API_KEY"
2. Send a message
curl -X POST https://rasayel.net/api/v1/messages \
  -H "Authorization: Bearer $RASAYEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channelId": "ch_01J9Z3",
    "to": "+201001234567",
    "text": "Hello from Rasayel 👋"
  }'

Guide

Send messages

POST /messages messages any phone number, email address or Telegram chat on a channel. If a conversation with them exists it continues; otherwise one is started and the contact is created.

To answer inside a conversation you already have, use POST /conversations/{id}/messages, which also takes "type": "note" for internal notes. Every message sent costs credit; see Usage in the app.

Reply in a conversation
curl -X POST https://rasayel.net/api/v1/conversations/cv_01J9Z4/messages \
  -H "Authorization: Bearer $RASAYEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Your order is on its way."
  }'

Guide

Receive with webhooks

Set one URL with PUT /webhook (or in Settings → API). Rasayel posts message.received, message.sent and message.updated from every channel, signed with your secret. Answer with any 2xx within 10 seconds.

Guide

Verify signatures

Check X-Rasayel-Signature against the raw body before parsing it, and reject anything older than five minutes.
Set your webhook
curl -X PUT https://rasayel.net/api/v1/webhook \
  -H "Authorization: Bearer $RASAYEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/rasayel/events"
  }'
Verify a delivery
import { createHmac, timingSafeEqual } from "node:crypto";

// header: X-Rasayel-Signature: t=<unix seconds>,v1=<hex>
export function verify(secret, rawBody, header) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
  const expected = createHmac("sha256", secret)
    .update(`${parts.t}.${rawBody}`)
    .digest("hex");
  return expected.length === parts.v1?.length &&
    timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}

Guide

Send files

Upload first with POST /files, then send the ids with the message in fileIds. Up to 10 files per message; the text may be empty. Links in responses are signed and work for 7 days.
Upload a file
curl -X POST https://rasayel.net/api/v1/files \
  -H "Authorization: Bearer $RASAYEL_API_KEY" \
  -F file=@invoice.pdf

Guide

Errors and limits

Every error has the same shape, with a code to branch on. Each key may make 600 requests a minute; lists are paged with nextCursor.
StatusCodeWhat it means
400invalid_requestSomething in the request is missing or wrong; the message says what.
401unauthenticatedNo key, or a revoked or unknown one.
403forbiddenNot allowed: a disabled channel, or starting conversations is turned off.
404not_foundNot in your organization.
409conflictIt already exists.
429rate_limitedOver 600 requests a minute; wait for Retry-After seconds.
503unavailableA temporary problem on our side; retry with backoff.
Error response
{
  "error": {
    "code": "invalid_request",
    "message": "`to` is required."
  }
}

API reference

Endpoints

Base URL https://rasayel.net/api/v1

Messages

Message any number or address on one of your channels.

Message any number or address on a channel

POST/messages

Continues the conversation with to on that channel, or starts one (the contact is created) while the platform allows starting conversations from the API; otherwise 403 for an address with no conversation yet. to is a phone number for WhatsApp (+201001234567), an email address for email, a chat id for Telegram.

Body

  • channelIdstringrequired
  • tostringrequired
  • textstringoptional

    Up to 10000 characters

  • namestringoptional

    The contact's name, when the contact is new.

  • subjectstringoptional

    Email subject for a new conversation.

  • fileIdsstring[]optional

    Ids from POST /files. Send text, fileIds or both.

    Up to 10 items

Responses

  • 201Sent
  • 202Stored but delivery failed; see `error`
  • 401Missing or invalid API key
  • 403The channel is disabled, or starting new conversations is turned off
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
POST /messages
curl -X POST https://rasayel.net/api/v1/messages \
  -H "Authorization: Bearer $RASAYEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channelId": "ch_01J9Z3",
    "to": "+201001234567",
    "text": "Your order is on its way.",
    "fileIds": [
      "fl_01J9Z6"
    ]
  }'
Response 201
{
  "data": {
    "id": "01J9Z3K7Q2X4",
    "conversationId": "cv_01J9Z4",
    "direction": "inbound",
    "type": "text",
    "text": "Your order is on its way.",
    "attachments": [
      {
        "name": "invoice.pdf",
        "mimeType": "application/pdf",
        "size": 48213,
        "fileId": "fl_01J9Z6",
        "href": "https://rasayel.net/api/files/…"
      }
    ],
    "status": "open",
    "createdAt": "2026-10-27T10:15:00.000Z"
  },
  "conversationId": "cv_01J9Z4"
}

Conversations

Read threads, reply, add internal notes, assign and resolve.

List conversations, most recent activity first

GET/conversations

Query parameters

  • statusenumoptional

    openpendingresolvedall

    Default "open"

  • assigneestringoptional

    A user id, or unassigned

  • channelIdstringoptional
  • cursorstringoptional
  • limitintegeroptional

Responses

  • 200OK
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
GET /conversations
curl https://rasayel.net/api/v1/conversations \
  -H "Authorization: Bearer $RASAYEL_API_KEY"
Response 200
{
  "data": [
    {
      "id": "01J9Z3K7Q2X4",
      "status": "open",
      "channel": {
        "id": "01J9Z3K7Q2X4",
        "name": "Ada Lovelace",
        "type": "whatsapp",
        "status": "open",
        "address": "201001234567"
      },
      "contact": {
        "id": "01J9Z3K7Q2X4",
        "name": "Ada Lovelace",
        "email": "ada@example.com",
        "phone": "+201001234567",
        "tags": [
          null
        ],
        "attributes": {},
        "lastSeenAt": "2026-10-27T10:15:00.000Z",
        "createdAt": "2026-10-27T10:15:00.000Z"
      },
      "assigneeId": null,
      "lastMessageAt": "2026-10-27T10:15:00.000Z",
      "unreadCount": 0
    }
  ],
  "nextCursor": null
}

Get a conversation

GET/conversations/{id}

Path parameters

  • idstringrequired

Responses

  • 200OK
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
GET /conversations/{id}
curl https://rasayel.net/api/v1/conversations/cv_01J9Z4 \
  -H "Authorization: Bearer $RASAYEL_API_KEY"

Change status or assignee

PATCH/conversations/{id}

Path parameters

  • idstringrequired

Body

  • statusenumoptional

    openpendingresolved

  • assigneeIdstring | nulloptional

Responses

  • 200OK
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
PATCH /conversations/{id}
curl -X PATCH https://rasayel.net/api/v1/conversations/cv_01J9Z4 \
  -H "Authorization: Bearer $RASAYEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "open",
    "assigneeId": null
  }'

List messages (pages go back in time)

GET/conversations/{id}/messages

Path parameters

  • idstringrequired

Query parameters

  • cursorstringoptional

Responses

  • 200OK
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
GET /conversations/{id}/messages
curl https://rasayel.net/api/v1/conversations/cv_01J9Z4/messages \
  -H "Authorization: Bearer $RASAYEL_API_KEY"
Response 200
{
  "data": [
    {
      "id": "01J9Z3K7Q2X4",
      "conversationId": "cv_01J9Z4",
      "direction": "inbound",
      "type": "text",
      "text": "Your order is on its way.",
      "attachments": [
        {
          "name": null,
          "mimeType": null,
          "size": null,
          "fileId": null,
          "href": null
        }
      ],
      "status": "open",
      "createdAt": "2026-10-27T10:15:00.000Z"
    }
  ],
  "nextCursor": null
}

Reply to the contact, or add an internal note

POST/conversations/{id}/messages

Path parameters

  • idstringrequired

Body

  • textstringoptional
  • typeenumoptional

    replynote

    Default "reply"

  • fileIdsstring[]optional

    Ids from POST /files. text may be empty when files are attached (replies only).

    Up to 10 items

Responses

  • 201Sent
  • 202Stored but delivery failed; see `error`
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
POST /conversations/{id}/messages
curl -X POST https://rasayel.net/api/v1/conversations/cv_01J9Z4/messages \
  -H "Authorization: Bearer $RASAYEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Your order is on its way.",
    "fileIds": [
      "fl_01J9Z6"
    ]
  }'
Response 201
{
  "data": {
    "id": "01J9Z3K7Q2X4",
    "conversationId": "cv_01J9Z4",
    "direction": "inbound",
    "type": "text",
    "text": "Your order is on its way.",
    "attachments": [
      {
        "name": "invoice.pdf",
        "mimeType": "application/pdf",
        "size": 48213,
        "fileId": "fl_01J9Z6",
        "href": "https://rasayel.net/api/files/…"
      }
    ],
    "status": "open",
    "createdAt": "2026-10-27T10:15:00.000Z"
  }
}

Contacts

The people you talk to, across every channel: their record, timeline and notes.

List or search contacts

GET/contacts

Query parameters

  • searchstringoptional
  • cursorstringoptional

Responses

  • 200OK
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
GET /contacts
curl https://rasayel.net/api/v1/contacts \
  -H "Authorization: Bearer $RASAYEL_API_KEY"
Response 200
{
  "data": [
    {
      "id": "01J9Z3K7Q2X4",
      "name": "Ada Lovelace",
      "email": "ada@example.com",
      "phone": "+201001234567",
      "tags": [
        "tag"
      ],
      "attributes": {},
      "lastSeenAt": "2026-10-27T10:15:00.000Z",
      "createdAt": "2026-10-27T10:15:00.000Z"
    }
  ],
  "nextCursor": null
}

Get a contact, with identities, conversations and a summary

GET/contacts/{id}

The summary counts messages each way, conversations open and in total, and the median first response for this person.

Path parameters

  • idstringrequired

Responses

  • 200OK
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
GET /contacts/{id}
curl https://rasayel.net/api/v1/contacts/ct_01J9Z5 \
  -H "Authorization: Bearer $RASAYEL_API_KEY"
Response 200
{
  "data": {
    "id": "01J9Z3K7Q2X4",
    "name": "invoice.pdf",
    "email": "ada@example.com",
    "phone": "+201001234567",
    "tags": [
      "tag"
    ],
    "attributes": {},
    "lastSeenAt": "2026-10-27T10:15:00.000Z",
    "createdAt": "2026-10-27T10:15:00.000Z",
    "identities": [
      {
        "channelType": "channelType",
        "address": "201001234567",
        "displayName": "displayName",
        "createdAt": "2026-10-27T10:15:00.000Z"
      }
    ],
    "conversations": [
      {
        "id": "01J9Z3K7Q2X4",
        "status": "open",
        "channel": {
          "id": null,
          "name": null,
          "type": null,
          "status": null,
          "address": null
        },
        "contact": {
          "id": null,
          "name": null,
          "email": null,
          "phone": null,
          "tags": null,
          "attributes": null,
          "lastSeenAt": null,
          "createdAt": null
        },
        "assigneeId": null,
        "lastMessageAt": "2026-10-27T10:15:00.000Z",
        "unreadCount": 0
      }
    ],
    "summary": {
      "conversations": 1,
      "active": 1,
      "received": 1,
      "sent": 1,
      "notes": null,
      "firstContactAt": "2026-10-27T10:15:00.000Z",
      "lastReceivedAt": "2026-10-27T10:15:00.000Z",
      "lastSentAt": "2026-10-27T10:15:00.000Z",
      "firstResponseMedian": 1,
      "channels": [
        "channel"
      ]
    }
  }
}

Update a contact

PATCH/contacts/{id}

Changes are recorded in the contact's history. notes is kept for older integrations: text sent there is added as a new note.

Path parameters

  • idstringrequired

Body

  • namestring | nulloptional
  • emailstring | nulloptional
  • phonestring | nulloptional
  • tagsstring[]optional
  • attributesobjectoptional
  • notesstring | nulloptional

Responses

  • 200OK
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
PATCH /contacts/{id}
curl -X PATCH https://rasayel.net/api/v1/contacts/ct_01J9Z5 \
  -H "Authorization: Bearer $RASAYEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Ada Lovelace",
    "email": "ada@example.com"
  }'
Response 200
{
  "data": {
    "id": "01J9Z3K7Q2X4",
    "name": "Ada Lovelace",
    "email": "ada@example.com",
    "phone": "+201001234567",
    "tags": [
      "tag"
    ],
    "attributes": {},
    "lastSeenAt": "2026-10-27T10:15:00.000Z",
    "createdAt": "2026-10-27T10:15:00.000Z"
  }
}

Erase a contact

DEL/contacts/{id}

Deletes the contact and everything about them: identities, conversations, messages, notes, history and the files they sent. It cannot be undone.

Path parameters

  • idstringrequired

Responses

  • 200Erased
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
DELETE /contacts/{id}
curl -X DELETE https://rasayel.net/api/v1/contacts/ct_01J9Z5 \
  -H "Authorization: Bearer $RASAYEL_API_KEY"
Response 200
{
  "data": {
    "id": "01J9Z3K7Q2X4",
    "deleted": true,
    "messages": 1,
    "files": 1
  }
}

A contact's timeline

GET/contacts/{id}/timeline

Everything that happened with a contact, newest first: messages on every channel, internal notes, status and assignment changes, notes about them, and profile changes. Pass nextCursor back as before for older items.

Path parameters

  • idstringrequired

Query parameters

  • beforestringoptional
  • limitintegeroptional

    Default 50

  • typesstringoptional
  • channelstringoptional

Responses

  • 200OK
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
GET /contacts/{id}/timeline
curl https://rasayel.net/api/v1/contacts/ct_01J9Z5/timeline \
  -H "Authorization: Bearer $RASAYEL_API_KEY"
Response 200
{
  "data": [
    {
      "kind": "message",
      "id": "01J9Z3K7Q2X4",
      "at": "2026-10-27T10:15:00.000Z",
      "message": {
        "id": "01J9Z3K7Q2X4",
        "conversationId": "cv_01J9Z4",
        "direction": "inbound",
        "type": "text",
        "text": "Your order is on its way.",
        "attachments": [
          null
        ],
        "status": "open",
        "createdAt": "2026-10-27T10:15:00.000Z"
      },
      "channel": {
        "id": "01J9Z3K7Q2X4",
        "name": "Ada Lovelace",
        "type": "whatsapp"
      },
      "authorName": "authorName",
      "note": {
        "id": "01J9Z3K7Q2X4",
        "body": "body",
        "pinned": false,
        "author": {
          "id": null,
          "name": null
        },
        "source": "user",
        "edited": false,
        "createdAt": "2026-10-27T10:15:00.000Z",
        "updatedAt": "2026-10-27T10:15:00.000Z"
      },
      "event": {
        "kind": "kind",
        "actorName": "actorName",
        "source": "source",
        "detail": {},
        "createdAt": "2026-10-27T10:15:00.000Z"
      }
    }
  ],
  "nextCursor": null
}

List a contact's notes

GET/contacts/{id}/notes

Path parameters

  • idstringrequired

Query parameters

  • beforestringoptional

Responses

  • 200OK
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
GET /contacts/{id}/notes
curl https://rasayel.net/api/v1/contacts/ct_01J9Z5/notes \
  -H "Authorization: Bearer $RASAYEL_API_KEY"
Response 200
{
  "data": [
    {
      "id": "01J9Z3K7Q2X4",
      "body": "body",
      "pinned": false,
      "author": {
        "id": "01J9Z3K7Q2X4",
        "name": "Ada Lovelace"
      },
      "source": "user",
      "edited": false,
      "createdAt": "2026-10-27T10:15:00.000Z",
      "updatedAt": "2026-10-27T10:15:00.000Z"
    }
  ],
  "nextCursor": null
}

Add a note to a contact

POST/contacts/{id}/notes

Path parameters

  • idstringrequired

Body

  • bodystringrequired

    Up to 10000 characters

  • pinnedbooleanoptional

    Default false

Responses

  • 201Added
  • 400Invalid note
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
POST /contacts/{id}/notes
curl -X POST https://rasayel.net/api/v1/contacts/ct_01J9Z5/notes \
  -H "Authorization: Bearer $RASAYEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "body"
  }'
Response 201
{
  "data": {
    "id": "01J9Z3K7Q2X4",
    "body": "body",
    "pinned": false,
    "author": {
      "id": "01J9Z3K7Q2X4",
      "name": "Ada Lovelace"
    },
    "source": "user",
    "edited": false,
    "createdAt": "2026-10-27T10:15:00.000Z",
    "updatedAt": "2026-10-27T10:15:00.000Z"
  }
}

Edit, pin or unpin a note

PATCH/contacts/{id}/notes/{noteId}

A key can change the text of notes written through the API, and pin or unpin any note.

Path parameters

  • idstringrequired
  • noteIdstringrequired

Body

  • bodystringoptional

    Up to 10000 characters

  • pinnedbooleanoptional

Responses

  • 200OK
  • 401Missing or invalid API key
  • 403Written by a teammate
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
PATCH /contacts/{id}/notes/{noteId}
curl -X PATCH https://rasayel.net/api/v1/contacts/ct_01J9Z5/notes/nt_01J9Z6 \
  -H "Authorization: Bearer $RASAYEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "body",
    "pinned": false
  }'
Response 200
{
  "data": {
    "id": "01J9Z3K7Q2X4",
    "body": "body",
    "pinned": false,
    "author": {
      "id": "01J9Z3K7Q2X4",
      "name": "Ada Lovelace"
    },
    "source": "user",
    "edited": false,
    "createdAt": "2026-10-27T10:15:00.000Z",
    "updatedAt": "2026-10-27T10:15:00.000Z"
  }
}

Delete a note

DEL/contacts/{id}/notes/{noteId}

Path parameters

  • idstringrequired
  • noteIdstringrequired

Responses

  • 200Deleted
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
DELETE /contacts/{id}/notes/{noteId}
curl -X DELETE https://rasayel.net/api/v1/contacts/ct_01J9Z5/notes/nt_01J9Z6 \
  -H "Authorization: Bearer $RASAYEL_API_KEY"

Channels

Your WhatsApp numbers, inboxes, bots, web chat and API channels.

List channels

GET/channels

Responses

  • 200OK
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
GET /channels
curl https://rasayel.net/api/v1/channels \
  -H "Authorization: Bearer $RASAYEL_API_KEY"
Response 200
{
  "data": [
    {
      "id": "01J9Z3K7Q2X4",
      "name": "Ada Lovelace",
      "type": "whatsapp",
      "status": "open",
      "address": "201001234567"
    }
  ]
}

Deliver an inbound message on an API channel

POST/channels/{id}/messages

Path parameters

  • idstringrequired

Body

  • contactobjectrequired

    idnameemailphone

  • textstringoptional

    Up to 10000 characters

  • externalIdstringoptional

    Your id for the message; retries with the same id are stored once.

  • fileIdsstring[]optional

    Ids from POST /files. Send text, fileIds or both.

    Up to 10 items

Responses

  • 201Stored
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
POST /channels/{id}/messages
curl -X POST https://rasayel.net/api/v1/channels/ch_01J9Z3/messages \
  -H "Authorization: Bearer $RASAYEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contact": {
      "id": "01J9Z3K7Q2X4",
      "name": "Ada Lovelace",
      "email": "ada@example.com",
      "phone": "+201001234567"
    },
    "text": "Your order is on its way.",
    "fileIds": [
      "fl_01J9Z6"
    ]
  }'
Response 201
{
  "data": {
    "id": "01J9Z3K7Q2X4",
    "conversationId": "cv_01J9Z4",
    "direction": "inbound",
    "type": "text",
    "text": "Your order is on its way.",
    "attachments": [
      {
        "name": "invoice.pdf",
        "mimeType": "application/pdf",
        "size": 48213,
        "fileId": "fl_01J9Z6",
        "href": "https://rasayel.net/api/files/…"
      }
    ],
    "status": "open",
    "createdAt": "2026-10-27T10:15:00.000Z"
  },
  "conversationId": "cv_01J9Z4"
}

Files

Upload attachments, then send them by id.

Upload a file to attach to a message

POST/files

Multipart body

  • filestringrequired

Responses

  • 201Stored
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
POST /files
curl -X POST https://rasayel.net/api/v1/files \
  -H "Authorization: Bearer $RASAYEL_API_KEY" \
  -F file=@invoice.pdf
Response 201
{
  "data": {
    "id": "01J9Z3K7Q2X4",
    "name": "invoice.pdf",
    "mimeType": "application/pdf",
    "size": 48213,
    "url": "https://example.com/rasayel/events"
  }
}

Event webhook

Where your system receives messages from every channel.

Your event webhook (URL and last delivery; never the secret)

GET/webhook

Responses

  • 200OK
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
GET /webhook
curl https://rasayel.net/api/v1/webhook \
  -H "Authorization: Bearer $RASAYEL_API_KEY"

Set the URL that receives message events from every channel

PUT/webhook

The signing secret is returned once, when it is first created or rotated.

Body

  • urlstringrequired
  • rotateSecretbooleanoptional

    Default false

Responses

  • 200OK
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
PUT /webhook
curl -X PUT https://rasayel.net/api/v1/webhook \
  -H "Authorization: Bearer $RASAYEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/rasayel/events"
  }'
Response 200
{
  "data": {
    "url": "https://example.com/rasayel/events",
    "secret": "whsec_…"
  }
}

Stop event deliveries

DEL/webhook

Responses

  • 200OK
  • 401Missing or invalid API key
  • 404Not found in your organization
  • 429Rate limited (600 requests/minute per key)
DELETE /webhook
curl -X DELETE https://rasayel.net/api/v1/webhook \
  -H "Authorization: Bearer $RASAYEL_API_KEY"

API reference

Webhook events

Every delivery has the same envelope: the event type, when it was sent, and the message with its conversation and contact.
  • message.received

    A contact wrote to you, on any channel.

  • message.sent

    A message went out: from Messenger, the API or automation.

  • message.updated

    A sent message changed status: delivered, read or failed.

Headers: X-Rasayel-Signature, X-Rasayel-Event, Content-Type: application/json.

message.received
{
  "type": "message.received",
  "createdAt": "2026-10-27T10:15:00.000Z",
  "data": {
    "channelId": "ch_01J9Z3",
    "channelType": "whatsapp",
    "conversationId": "cv_01J9Z4",
    "message": {
      "id": "ms_01J9Z7",
      "direction": "inbound",
      "senderType": "contact",
      "type": "text",
      "text": "Is my order shipped?",
      "status": "received",
      "attachments": [],
      "createdAt": "2026-10-27T10:15:00.000Z"
    },
    "contact": {
      "id": "ct_01J9Z5",
      "address": "201001234567",
      "name": "Ada Lovelace",
      "phone": "+201001234567",
      "email": null
    }
  }
}

API reference

Objects

The shapes returned by the API.

Channel

Attributes

  • idstring
  • namestring
  • typeenum

    whatsappemailtelegramchatformapi

  • statusstring
  • addressstring | null

Contact

Attributes

  • idstring
  • namestring | null
  • emailstring | null
  • phonestring | null
  • tagsstring[]
  • attributesobject
  • lastSeenAtstring | null
  • createdAtstring

Conversation

Attributes

  • idstring
  • statusstring
  • channelChannel
  • contactContact
  • assigneeIdstring | null
  • lastMessageAtstring
  • unreadCountinteger

Message

Attributes

  • idstring
  • conversationIdstring
  • directionenum

    inboundoutbound

  • typeenum

    textmedianoteevent

  • textstring | null
  • attachmentsAttachment[]
  • statusstring
  • createdAtstring

Attachment

Attributes

  • namestring
  • mimeTypestring
  • sizeinteger | null
  • fileIdstring | null
  • hrefstring | null

    Signed link, valid for 7 days

ContactProfile

Attributes

  • idstring
  • namestring | null
  • emailstring | null
  • phonestring | null
  • tagsstring[]
  • attributesobject
  • lastSeenAtstring | null
  • createdAtstring
  • identitiesobject[]
  • conversationsConversation[]
  • summaryobject

    conversationsactivereceivedsentnotesfirstContactAtlastReceivedAtlastSentAtfirstResponseMedianchannels

Note

Attributes

  • idstring
  • bodystring
  • pinnedboolean
  • authorobject | null

    idname

  • sourceenum

    userapisystem

  • editedboolean
  • createdAtstring
  • updatedAtstring

TimelineItem

Attributes

  • kindenum

    messagenoteprofileidentitycreated

  • idstring
  • atstring
  • messageMessage
  • channelobject

    idnametype

  • authorNamestring | null
  • noteNote
  • eventobject

    kindactorNamesourcedetailcreatedAt

File

Attributes

  • idstring
  • namestring
  • mimeTypestring
  • sizeinteger
  • urlstring