1. Docs
  2. Integrations
  3. Slack

Build a Slack astrology bot with RoxyAPI

Add /horoscope, /tarot, and /lifepath slash commands to any Slack workspace in under 20 minutes. Bolt SDK, Block Kit replies, RoxyAPI on the backend.

Slack is the workspace messaging platform with the most developer-friendly bot surface: slash commands, the Events API, and the official Bolt SDK for Node.js and Python. RoxyAPI provides the spiritual data layer: 130+ astrology, Vedic astrology, tarot, and numerology endpoints behind one key, plus a remote MCP server per domain for AI-routed bots.

TL;DR

  • You will ship a Slack bot that responds to /horoscope aries, /tarot, and /lifepath 1990-05-15 with rich Block Kit replies
  • You need a Slack app at api.slack.com/apps (free) with commands and chat:write scopes, plus a RoxyAPI key. Plans start at $39 a month for 25K requests; a free test key is available on request via contact
  • Working code in three languages, ready to deploy. About 15 minutes start to finish

What you can build on Slack

  • A workspace /horoscope slash command that posts the daily reading as a Block Kit card
  • A /tarot command that draws a daily card and embeds the card image in the reply
  • A /lifepath <YYYY-MM-DD> numerology command for onboarding rituals (new hire shoutouts, anniversaries)
  • A scheduled morning post that drops the daily moon phase or panchang into a #standup channel
  • An interactive /synastry command that asks for two members and returns a compatibility score
  • An AI agent bot where the LLM picks between horoscope, kundli, and tarot endpoints based on the message
  • A workspace assistant that uses Block Kit context blocks to surface lucky number, moon sign, and energy rating

What you need, 30 seconds

  1. A Slack workspace where you can install apps. Free.
  2. A Slack app created at api.slack.com/apps with three pieces wired up: a slash command, a Bot Token (xoxb-...), and a Signing Secret. The Bolt JS getting-started guide and Bolt Python getting-started guide walk through the console step by step.
  3. A RoxyAPI key. Plans start at $39 a month on the pricing page; a free test key for evaluation is available on request via contact.
  4. A public HTTPS endpoint or Slack Socket Mode for local dev.
  5. About 15 minutes.

Run the quickstart curl in a terminal first. A 200 response confirms the Roxy key is good before Slack tries to deliver any slash command.

Step 1, register the slash command and pick a transport

In the Slack app console, open Slash Commands, click Create New Command:

  • Command /horoscope
  • Request URL https://your-app.example.com/slack/events (the Bolt default)
  • Short description "Get the daily horoscope"
  • Usage hint [zodiac sign]

Add the commands and chat:write OAuth scopes, install the app to your workspace, copy the Bot User OAuth Token and Signing Secret. Slack offers two transports for delivering events to your handler.

Slack POSTs every slash command and event to your Request URL. Bolt verifies the signing secret on every request automatically.

# Slack will fire something like this
curl -X POST "https://your-app.example.com/slack/events" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d 'command=/horoscope&text=aries&user_id=U123&channel_id=C456'

Your endpoint must be HTTPS. Use ngrok for local dev. The whole verify-and-route dance is handled by Bolt; you just register the command handler.

Step 2, ship the /horoscope command

The handler reads the zodiac sign from the slash command text, calls Roxy, and replies with a Block Kit card. The example uses HTTP transport, but the body of the handler is identical under Socket Mode.

curl "https://roxyapi.com/api/v2/astrology/horoscope/aries/daily" \
  -H "X-API-Key: $ROXY_API_KEY"

You should get back JSON with sign, date, overview, love, career, luckyNumber, moonSign, moonPhase, and energyRating. Map them into Block Kit blocks below.

Type /horoscope aries in any channel where the app is installed. The reply lands inline as a richly formatted card.

Bonus, a /tarot command with the card image

The tarot/daily response carries card.imageUrl, a public CDN URL. The Block Kit image block accepts a remote URL directly, so you can return the card image with no extra hosting.

app.command('/tarot', async ({ command, ack, respond }) => {
  await ack();
  const { data } = await roxy.tarot.getDailyCard({
    body: { seed: command.user_id }, // deterministic per user per day
  });
  await respond({
    blocks: [
      {
        type: 'image',
        image_url: data.card.imageUrl,
        alt_text: data.card.name,
        title: {
          type: 'plain_text',
          text: `${data.card.name}${data.card.reversed ? ' (reversed)' : ''}`,
        },
      },
      { type: 'section', text: { type: 'mrkdwn', text: data.dailyMessage } },
    ],
  });
});

Seeding by command.user_id makes the daily card deterministic per user per day. Same Slack member calls /tarot ten times before midnight, gets the same card every time. Add the files:write scope if you want to upload images directly instead of linking the CDN URL.

Step 3, scale to the full surface

Adding a new slash command is the same shape as /horoscope. Pick the endpoint, build the parameters, format the Block Kit response.

Any chart, panchang, dasha, dosha, KP, synastry, or compatibility endpoint needs latitude, longitude, and timezone. Always call roxy.location.searchCities (TS) or roxy.location.search_cities (Py) first. Pass the IANA timezone straight through; the server resolves DST for the chart date.

Add an MCP-powered AI agent (optional)

For free-text questions in DMs ("what does my chart say about my career?"), point an LLM at the Roxy MCP server and let it pick the endpoint.

The remote MCP server runs at https://roxyapi.com/mcp/{domain} over Streamable HTTP. No stdio, no Docker, no local setup. Point Claude Code, Cursor, OpenAI Agents SDK, or any other MCP-aware client at the URL with your X-API-Key header. Inside a Bolt app.message handler, forward the message text to the agent, await the answer, post it back via say() or respond().

tools/list is free. Every tools/call bills the same as the equivalent REST call. See /docs/mcp for the full setup.

Frequently asked questions

Why does Bolt verify signing secrets automatically?

Slack signs every webhook POST with HMAC SHA256. Bolt checks the X-Slack-Signature and X-Slack-Request-Timestamp headers on every request and rejects mismatches before your handler runs. You only set signingSecret in the App constructor; the rest is handled.

Can I call ack() after a long Roxy call?

No. Slack expects an ack within 3 seconds. Always call await ack() first, then call Roxy, then respond() (which posts via the response_url Slack passes in the slash command payload). The example handlers above follow this pattern.

How do I keep the bot from leaking horoscopes to the wrong channel?

By default respond() replies in the channel where the slash command was issued. To DM a user instead, switch to client.chat.postMessage({ channel: command.user_id, ... }) (Slack accepts user IDs as DM channels) or set the slash command response_type to ephemeral so only the invoking user sees it.

Can the bot reply in Hindi, Spanish, or Turkish?

Yes. Most Roxy domains accept a lang query parameter (en, tr, de, es, fr, hi, pt, ru). In the SDK, pass query: { lang: 'hi' } (TS) or lang='hi' (Py). Detect the user language from the workspace locale or a per-user preference.

What scopes do I need beyond commands?

chat:write to post messages back. Add files:write only if you want to upload images directly (linking the imageUrl CDN URL in a Block Kit image block does not need it). For DMs, add im:write.

Gotchas

  • Backend-only key. The Roxy key and Slack tokens both live in your handler. Never echo either to a channel, never check them into git.
  • 3-second ack budget. Always await ack() first, then call Roxy. The slash command will time out if you hold the ack for the API call.
  • response_url is good for 30 minutes. respond() uses it under the hood. After 30 minutes, post via client.chat.postMessage instead.
  • Rate limits are tier-based. Most workspaces sit at Tier 3 (50 calls per minute on chat.postMessage). Bolt does not throttle for you, so heavy bulk sends need explicit pacing.
  • Block Kit text fields cap at 3000 chars. The Roxy overview field is short, but interpretation.detailed from a natal chart can be longer. Truncate or split into multiple section blocks.
  • Slack mrkdwn is not Markdown. Bold is *text* (single asterisks), italic is _text_. Code is single backticks. No real headers (use a header block instead).
  • Timezone IANA wins. Prefer "Asia/Kolkata" to 5.5. The server resolves DST per chart date.
  • MCP tools/call is billable, tools/list is free. When debugging an agent, the discovery call does not count, the actual answer does.

What to build next