Ray
PricingDocsSign inStart free
Browse the docs

Getting started

Ray documentationAuthenticationUsing Ray with AI coding agentsMCP serverTypeScript SDK

Guides

Sending notificationsIdempotencyTemplatesScheduling and test sendsStatus and feedsClick trackingDelivery webhooks

Channels

Email with Amazon SESEmail with SMTPPush notifications with Firebase Cloud MessagingSlack notificationsDiscord notificationsTelegram notificationsSMS with TwilioSMS with sendsms.mnHTTPS webhook channel

Reference

Rate limits and quotasErrors

Getting started

Ray documentationAuthenticationUsing Ray with AI coding agentsMCP serverTypeScript SDK

Guides

Sending notificationsIdempotencyTemplatesScheduling and test sendsStatus and feedsClick trackingDelivery webhooks

Channels

Email with Amazon SESEmail with SMTPPush notifications with Firebase Cloud MessagingSlack notificationsDiscord notificationsTelegram notificationsSMS with TwilioSMS with sendsms.mnHTTPS webhook channel

Reference

Rate limits and quotasErrors

Channels

Slack notifications

Post Ray notifications to a Slack channel through an incoming webhook. Slack app setup, config, mrkdwn content, pacing, escaping and errors.

View as Markdownllms.txtAPI reference

The slack_webhook channel posts messages to a Slack channel through a Slack incoming webhook URL. The webhook URL decides the channel, so there is no per-message recipient. API calls go to https://ray-api.gege.mn with Authorization: Bearer $RAY_API_KEY.

Channel type slack_webhook
Template kind slack_text
Recipient {}
Pacing 1 message per second per webhook URL
Suppression None

What you need from Slack

  1. Go to https://api.slack.com/apps and click Create New App, From scratch. Name it (for example Ray alerts) and pick your workspace.
  2. In the app settings open Incoming Webhooks and turn Activate Incoming Webhooks on.
  3. Click Add New Webhook to Workspace, choose the channel to post to, and allow.
  4. Copy the webhook URL. It looks like https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX.

Each webhook posts to one channel. To post to several channels, create one webhook (and one Ray channel config) per channel. Treat the URL as a secret: anyone with it can post to the channel.

Channel config

Create the config in the dashboard: Channels, New channel, Slack webhook. The URL is stored encrypted; after saving, the dashboard only shows its host.

Field Required Notes
Name yes Internal label, for example eng-alerts.
Webhook URL (webhookUrl) yes Must be on hooks.slack.com. Any other host is refused when sending (the delivery fails as failed_terminal). When editing, leave blank to keep the stored URL.

Find the config's id with GET /channels; its kind is slack_webhook.

Template content

Field Type Notes
text string, 1 to 40,000 Slack mrkdwn: *bold*, _italic_, ~strike~, <https://example.com|link text>, line breaks with \n.

Escaping: in param values Ray replaces &, < and > with &amp;, &lt; and &gt;. A value can't inject a link (<https://...|...>) or a mention (<!channel>, <@U123>), but *, _ and ~ in a value still format, because Slack has no escape for them. Put links and mentions in the template text, not in params.

Recipient

Always an empty object:

{}

Unknown keys are ignored.

Send a message

curl -X POST https://ray-api.gege.mn/send \
  -H "Authorization: Bearer $RAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channelConfigId": "7c8d9e0f-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
    "content": {
      "text": "*{{service}}* error rate is {{rate}}%\n<https://status.example.com|Open status page>"
    },
    "params": { "service": "billing-api", "rate": 4.2 },
    "recipient": {}
  }'
async function slackAlert(service: string, rate: number) {
  const res = await fetch("https://ray-api.gege.mn/send", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.RAY_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      channelConfigId: "7c8d9e0f-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
      templateId: "1d2e3f4a-5b6c-4d7e-8f9a-0b1c2d3e4f5a", // a slack_text template
      params: { service, rate },
      recipient: {},
    }),
  });
  if (res.status !== 202) throw new Error(`Ray ${res.status}: ${await res.text()}`);
}

A slack_text template for the same message:

{
  "name": "Error rate alert",
  "channelKind": "slack_text",
  "content": { "text": "*{{service}}* error rate is {{rate}}%\n<https://status.example.com|Open status page>" },
  "logTitle": "Error rate alert",
  "logDescription": "{{service}} error rate {{rate}}%",
  "publish": true
}

Slack returns no message id, so the delivery row's providerMessageId is slack-<rowId>. delivered means Slack answered 200 ok.

Pacing

Slack allows about one message per second per incoming webhook, so Ray sends at most one message per second per webhook URL. Bursts queue up and drain at that rate; two Ray configs with the same URL share the pace. Use targets[] only if you really mean to post the same message several times; for alerting at volume, aggregate messages first.

Errors

Errors appear on the delivery row as providerError: { "name": "SlackWebhookError", "message": "Slack webhook failed: <status> <statusText> <body>" }.

Result Cases
failed_terminal (not retried) Any HTTP 4xx except 429, such as invalid_payload, no_service (webhook revoked or app removed), channel_not_found, channel_is_archived, action_prohibited; a webhook URL that isn't on hooks.slack.com or isn't a valid URL
failed_retryable (retried) HTTP 429 (rate limited), HTTP 5xx, network errors and timeouts

Common fixes:

  • no_service or 404: the webhook was revoked or the app uninstalled. Create a new webhook and update the config.
  • channel_is_archived: unarchive the channel or create a webhook for another channel.
  • refusing to POST to non-Slack host: the configured URL isn't a hooks.slack.com webhook.

Request errors from POST /send are listed in Errors.

PreviousPush notifications with Firebase Cloud MessagingNextDiscord notifications

On this page

  • What you need from Slack
  • Channel config
  • Template content
  • Recipient
  • Send a message
  • Pacing
  • Errors
Ray

Notification delivery for teams that already have providers.

Product

PricingDocsAPI referenceMCP serverTypeScript SDKAgent skillsllms.txt

Legal

TermsPrivacyRefunds

Contact

[email protected]

© 2026 L’Atelier Gege LLC