ViablyViably
๐Ÿ“กWebhook Relay

Send events from your site to Slack

Webhook Relay lets you forward any event โ€” form submissions, payments, deployments, signups โ€” to a Slack channel in seconds. One endpoint handles all your event types. No server infrastructure required.

How it works

โš ๏ธ Before you start:Invite @Via to the Slack channel where you want webhooks to appear. Without this, Viably will accept your webhook but cannot post to the channel.
Step 1

Create an endpoint

In your Viably dashboard, create a relay endpoint and assign it to one or more Slack channels. You'll receive a URL and a secret token.

Step 2

POST a JSON payload

From your site or service, send a POST request with your event data. Include a type field to route it to the right Slack message template.

Step 3

See it in Slack

Viably formats the payload into a clean Block Kit message and posts it to your channel โ€” immediately, or batched on a schedule you choose. Stripe charge and subscription events are combined into a single summary card.

Environment variables

After creating an endpoint in the dashboard, add these to your project's environment:
VIABLY_RELAY_URL=https://hq.viably.app/<your-endpoint-provided>
VIABLY_RELAY_TOKEN=<your-secret-token>

Both values are shown in the dashboard immediately after creating an endpoint. Your token is only displayed once โ€” store it somewhere safe.

TypeScript types

Drop this into your project as viablyTypes.ts. Each event type carries its own recommended fields โ€” Viably will surface a hint in Slack when a recommended field is missing.
viablyTypes.ts
// viablyTypes.ts

export type ViablyEventType =
  | "transaction"
  | "leadgen"
  | "signups"
  | "contactform"
  | "devops"
  | "others"
  | "ocr";

type ViablyPayloadBase = {
  /** Routes the event to the right Slack template. Defaults to "others" if unrecognised. */
  type: ViablyEventType;
  /** Recommended. Identifies the origin โ€” e.g. "My Site โ€” Contact Page". */
  source?: string;
  /** ISO 8601 timestamp. Viably formats it using your workspace timezone. */
  submitted_at?: string;
  /** Override the default Slack channels set in your dashboard. */
  channels?: string[];
  [key: string]: unknown;
};

export type ViablyTransactionPayload = ViablyPayloadBase & {
  type: "transaction";

Sending a payload

A minimal helper and three common usage examples. Any additional fields you include beyond the recognized ones will appear in the Slack message as extra context.
// lib/viably.ts
import type { ViablyPayload } from "./viablyTypes";

export async function sendToViably(payload: ViablyPayload): Promise<void> {
  const res = await fetch(process.env.VIABLY_RELAY_URL!, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${process.env.VIABLY_RELAY_TOKEN}`,
    },
    body: JSON.stringify(payload),
  });
  if (!res.ok) throw new Error(`Viably relay failed: ${res.status}`);
}

// --- Contact form submission ---
await sendToViably({
  type: "contactform",
  source: "My Site โ€” Contact Page",
  message: form.message,
  email: form.email,
  name: form.name,
  submitted_at: new Date().toISOString(),
});

Event types

The type field routes the event to the matching Slack message template. If omitted or unrecognised, it falls back to others. Viably adds an inline ๐Ÿ’ก hint to the Slack message when a recommended field is absent.
typeDescriptionRecommended fields
transactionPayments, purchases, and financial events
amount
leadgenLead captures, downloads, and gated content fills
email
signupsNew user or account registrations
email
contactformContact or enquiry form submissions
messageemail
devopsDeployments, CI/CD results, and infrastructure alerts
titlestatus
othersAnything that doesn't fit a specific categoryโ€”
ocrReserved for Viably OCR integrations. Results are silently routed back to the originating Slack thread โ€” nothing is posted to the relay's configured channel.
job_idmessagepart
source (all types) โ€” A human-readable label for the origin of the event, e.g. "My Site โ€” Contact Page". Viably uses this for footer attribution on every message. If omitted, it falls back to the HTTP Referer/Origin header, then to the domain you set on the endpoint in the dashboard.
submitted_at (all types) โ€” An ISO 8601 timestamp for when the event occurred, e.g. new Date().toISOString(). Viably formats it using your workspace's default timezone and displays it as a Submitted at field in the Slack message. If omitted, no timestamp is shown.

Channel override

By default, events are posted to the Slack channels you configured on the endpoint. You can override this per-event by including a channelsarray in your payload. If Viably can't access any of the override channels, it falls back to the endpoint defaults automatically.
// Send to specific channels, overriding the defaults in your dashboard
await sendToViably({
  type: "devops",
  source: "GitHub Actions",
  title: "Production deploy",
  status: "deployed",
  channels: ["C0123456789", "C9876543210"], // Slack channel IDs
});

Channel IDs can be found by right-clicking a channel in Slack โ†’ View channel details โ†’ copy the ID at the bottom.

Stripe Integration

Viably can receive events directly from Stripe and post them to Slack. Because Stripe webhook destinations post to a plain URL, you must use the query-param token format โ€” not the Bearer authorization header.
  1. 1

    Create a relay endpoint

    In the Viably dashboard, create a new relay endpoint with Stripe Integration enabled. Once created, open the token dialog and copy the Stripe / query-param URL โ€” it looks like https://hq.viably.app/relay?token=โ€ฆ.

  2. 2

    Create a webhook destination in Stripe

    In your Stripe Dashboard, go to Developers โ†’ Webhooks โ†’ Add destination. Paste the Viably query-param URL as the Endpoint URL. Select these two events: charge.succeeded, and customer.subscription.updated.

    charge.succeededin particular would have captured all your successful transactions in Slack, whether they originated from Stripe Checkout, or from your own custom integration using Stripe's APIs. Viably looks for this event's payload to extract the correct amount, currency, and description to build out your transaction messages in Slack.

    You should not send any other Stripe events to this Webhook Relay endpoint, as that could cause an unexpected heavy load of message in your workspace and even causing double notifications or double-counting in revenue tracking.

  3. 3

    Copy the signing secret

    After saving, Stripe displays a signing secret beginning with whsec_. Copy it to complete your setup on Viably. If you miss it, you can reveal or roll it from the destination details page.

  4. 4

    Complete setup in Viably

    Back in the Viably dashboard, click Edit on the relay endpoint. Paste the whsec_โ€ฆ value into the Stripe webhook secret field and save. Viably will now verify every incoming Stripe request and reject anything unsigned.

  5. 5

    Test it

    Use Stripe's Send test event button on the destination page to fire a sample event. Check your configured Slack channel โ€” you should see a formatted message within a few seconds.

Why the query-param URL? Stripe webhook destinations send a plain POST โ€” they do not support custom Authorization headers. The ?token=โ€ฆ format is the Viably-supported alternative for these integrations. Both URLs are shown in the token dialog after endpoint creation.
EventHow Viably renders it
charge.*Transaction card โ€” amount, customer name, email, phone, location from billing_details. In batch mode, each charge is a row in a per-transaction table.
customer.subscription.updatedInformational card showing plan, price, and customer ID. Automatically detects cancellation, new activation, or generic update. Rapid-fire events for the same subscription within ~90 s are deduplicated.

Any extra fields are welcome

Beyond the recognised fields, you can include anything in the payload โ€” city, plan, current_page_url, custom metadata. Viably will render them as additional context in the Slack message so nothing is lost.