> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Slack

> Integrate Dodo Payments with Slack to receive real-time notifications about your payments.

## Introduction

The Dodo Payments Slack integration allows you to receive real-time notifications about your payments directly in your Slack workspace. This integration enables you to stay updated on the status of your payments, track transactions, and manage your payments more efficiently.

<Info>
  This integration uses our webhook management portal to automatically transform Dodo Payments webhook events into Slack-compatible messages. No additional coding is required - just configure the connector and start receiving notifications.
</Info>

## Getting Started

<Steps>
  <Step title="Open the Webhook Section">
    Go to the <b>Webhook</b> section in your Dodo Payments dashboard. Click the <b>+ Add Endpoint</b> button, then open the webhook dropdown to reveal other integrations.

    <Frame>
      <img src="https://mintcdn.com/dodopayments/slbAEdrLLwKHfaRf/images/integrations/slack/1.png?fit=max&auto=format&n=slbAEdrLLwKHfaRf&q=85&s=46218103ebf0646011873758c76b9bb6" alt="Dodo Payments dashboard showing Add Endpoint button and integrations dropdown" style={{ maxHeight: '500px', width: 'auto' }} width="1782" height="1016" data-path="images/integrations/slack/1.png" />
    </Frame>
  </Step>

  <Step title="Select Slack Integration">
    Select the <b>Slack</b> integration and click <b>Connect your Slack workspace</b>.

    <Frame>
      <img src="https://mintcdn.com/dodopayments/slbAEdrLLwKHfaRf/images/integrations/slack/2.png?fit=max&auto=format&n=slbAEdrLLwKHfaRf&q=85&s=4bd696f82dbbab1bc099c6ccae5b9212" alt="Slack integration card and connect button" style={{ maxHeight: '500px', width: 'auto' }} width="1670" height="226" data-path="images/integrations/slack/2.png" />
    </Frame>
  </Step>

  <Step title="Grant Slack Permissions">
    Grant the necessary permissions to the Incoming Webhooks Slack App so it can post messages in your chosen channel.

    <Frame>
      <img src="https://mintcdn.com/dodopayments/slbAEdrLLwKHfaRf/images/integrations/slack/3.png?fit=max&auto=format&n=slbAEdrLLwKHfaRf&q=85&s=00f04516a2720e377a29551ae42ad812" alt="Slack OAuth permissions screen for Incoming Webhooks app" style={{ maxHeight: '500px', width: 'auto' }} width="1198" height="1536" data-path="images/integrations/slack/3.png" />
    </Frame>
  </Step>

  <Step title="Customize Transformation Code">
    Add or edit the transformation code to customize your Slack notifications for your use case. You can use the pre-made templates or write your own logic.

    <Frame>
      <img src="https://mintcdn.com/dodopayments/slbAEdrLLwKHfaRf/images/integrations/slack/4.png?fit=max&auto=format&n=slbAEdrLLwKHfaRf&q=85&s=f3c7f2b7a9bb6d6ba1d1d6922ad42bc4" alt="Transformation code editor for Slack integration" style={{ maxHeight: '500px', width: 'auto' }} width="1686" height="1118" data-path="images/integrations/slack/4.png" />
    </Frame>
  </Step>

  <Step title="Test and Create">
    Test your transformation code with custom or pre-made event payloads. Once you're satisfied, click <b>Create</b> to activate the integration.

    <Frame>
      <img src="https://mintcdn.com/dodopayments/slbAEdrLLwKHfaRf/images/integrations/slack/5.png?fit=max&auto=format&n=slbAEdrLLwKHfaRf&q=85&s=7d22a91488a2038a177324fa627b7497" alt="Test transformation and create button" style={{ maxHeight: '500px', width: 'auto' }} width="1852" height="490" data-path="images/integrations/slack/5.png" />
    </Frame>
  </Step>

  <Step title="Integration Complete!">
    🎉 You have successfully created the Slack integration! Your Dodo Payments events will now be delivered to your selected Slack channel in real time.
  </Step>
</Steps>

## Transformation Code Examples

### Basic Payment Notifications

This transformation sends simple text messages for payment events:

```javascript payment_notifs.js icon="js" expandable theme={null}
function handler(webhook) {
  switch (webhook.eventType) {
    case "payment.succeeded":
      webhook.payload = {
        text: `✅ Payment Successful\nAmount: $${(webhook.payload.data.total_amount / 100).toFixed(2)}\nCustomer: ${webhook.payload.data.customer.email}\nPayment ID: ${webhook.payload.data.payment_id}`
      };
      break;
      
    case "payment.failed":
      webhook.payload = {
        text: `❌ Payment Failed\nAmount: $${(webhook.payload.data.total_amount / 100).toFixed(2)}\nCustomer: ${webhook.payload.data.customer.email}\nReason: ${webhook.payload.data.error_message || 'Unknown'}`
      };
      break;
      
    case "payment.processing":
      webhook.payload = {
        text: `⏳ Payment Processing\nAmount: $${(webhook.payload.data.total_amount / 100).toFixed(2)}\nCustomer: ${webhook.payload.data.customer.email}`
      };
      break;
  }

  return webhook;
}
```

### Rich Subscription Notifications

This transformation creates rich Slack messages with attachments for subscription events:

```javascript subscription_notifs.js icon="js" expandable theme={null}
function handler(webhook) {
  switch (webhook.eventType) {
    case "subscription.active":
      webhook.payload = {
        attachments: [{
          color: "good",
          title: "🎉 Subscription Activated",
          fields: [
            {
              title: "Customer",
              value: webhook.payload.data.customer.email,
              short: true
            },
            {
              title: "Product ID",
              value: webhook.payload.data.product_id,
              short: true
            },
            {
              title: "Amount",
              value: `$${(webhook.payload.data.recurring_pre_tax_amount / 100).toFixed(2)}/${webhook.payload.data.payment_frequency_interval}`,
              short: true
            },
            {
              title: "Next Billing",
              value: new Date(webhook.payload.data.next_billing_date).toLocaleDateString(),
              short: true
            }
          ],
          footer: "Dodo Payments",
          ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
        }]
      };
      break;
      
    case "subscription.cancelled":
      webhook.payload = {
        attachments: [{
          color: "warning",
          title: "⚠️ Subscription Cancelled",
          fields: [
            {
              title: "Customer",
              value: webhook.payload.data.customer.email,
              short: true
            },
            {
              title: "Product ID",
              value: webhook.payload.data.product_id,
              short: true
            },
            {
              title: "Cancellation Date",
              value: new Date(webhook.payload.data.cancelled_at).toLocaleDateString(),
              short: true
            },
            {
              title: "Cancel at Next Billing",
              value: webhook.payload.data.cancel_at_next_billing_date ? "Yes" : "No",
              short: true
            }
          ],
          footer: "Dodo Payments",
          ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
        }]
      };
      break;
      
    case "subscription.renewed":
      webhook.payload = {
        attachments: [{
          color: "good",
          title: "🔄 Subscription Renewed",
          fields: [
            {
              title: "Customer",
              value: webhook.payload.data.customer.email,
              short: true
            },
            {
              title: "Product ID",
              value: webhook.payload.data.product_id,
              short: true
            },
            {
              title: "Amount",
              value: `$${(webhook.payload.data.recurring_pre_tax_amount / 100).toFixed(2)}`,
              short: true
            },
            {
              title: "Next Billing",
              value: new Date(webhook.payload.data.next_billing_date).toLocaleDateString(),
              short: true
            }
          ],
          footer: "Dodo Payments",
          ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
        }]
      };
      break;
  }

  return webhook;
}
```

### Dispute Management Notifications

This transformation handles dispute events with appropriate colors and urgency:

```javascript dispute_notifs.js icon="js" expandable theme={null}
function handler(webhook) {
  switch (webhook.eventType) {
    case "dispute.opened":
      webhook.payload = {
        attachments: [{
          color: "danger",
          title: "🚨 New Dispute Opened",
          fields: [
            {
              title: "Payment ID",
              value: webhook.payload.data.payment_id,
              short: true
            },
            {
              title: "Amount",
              value: `$${(webhook.payload.data.amount / 100).toFixed(2)}`,
              short: true
            },
            {
              title: "Status",
              value: webhook.payload.data.dispute_status,
              short: true
            },
            {
              title: "Stage",
              value: webhook.payload.data.dispute_stage,
              short: true
            },
            {
              title: "Remarks",
              value: webhook.payload.data.remarks || "No remarks",
              short: false
            }
          ],
          footer: "Dodo Payments - Action Required",
          ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
        }]
      };
      break;
      
    case "dispute.won":
      webhook.payload = {
        attachments: [{
          color: "good",
          title: "✅ Dispute Won",
          fields: [
            {
              title: "Payment ID",
              value: webhook.payload.data.payment_id,
              short: true
            },
            {
              title: "Amount",
              value: `$${(webhook.payload.data.amount / 100).toFixed(2)}`,
              short: true
            },
            {
              title: "Status",
              value: webhook.payload.data.dispute_status,
              short: true
            },
            {
              title: "Resolution",
              value: "Dispute resolved in your favor",
              short: false
            }
          ],
          footer: "Dodo Payments",
          ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
        }]
      };
      break;
      
    case "dispute.lost":
      webhook.payload = {
        attachments: [{
          color: "danger",
          title: "❌ Dispute Lost",
          fields: [
            {
              title: "Payment ID",
              value: webhook.payload.data.payment_id,
              short: true
            },
            {
              title: "Amount",
              value: `$${(webhook.payload.data.amount / 100).toFixed(2)}`,
              short: true
            },
            {
              title: "Status",
              value: webhook.payload.data.dispute_status,
              short: true
            },
            {
              title: "Impact",
              value: "Funds will be debited from your account",
              short: false
            }
          ],
          footer: "Dodo Payments - Review Required",
          ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
        }]
      };
      break;
  }

  return webhook;
}
```

### Comprehensive All-Events Handler

This transformation handles all event types with consistent formatting:

```javascript all_events_notifs.js icon="js" expandable  theme={null}
function handler(webhook) {
  const event = webhook.payload.data;
  const timestamp = new Date(webhook.payload.timestamp).toLocaleString();
  
  let color, emoji, title, fields = [];
  
  switch (webhook.eventType) {
    case "payment.succeeded":
      color = "good";
      emoji = "✅";
      title = "Payment Successful";
      fields = [
        { title: "Amount", value: `$${(event.total_amount / 100).toFixed(2)}`, short: true },
        { title: "Customer", value: event.customer.email, short: true },
        { title: "Payment ID", value: event.payment_id, short: true },
        { title: "Method", value: event.payment_method || "Unknown", short: true }
      ];
      break;
      
    case "payment.failed":
      color = "danger";
      emoji = "❌";
      title = "Payment Failed";
      fields = [
        { title: "Amount", value: `$${(event.total_amount / 100).toFixed(2)}`, short: true },
        { title: "Customer", value: event.customer.email, short: true },
        { title: "Reason", value: event.error_message || "Unknown", short: false }
      ];
      break;
      
    case "subscription.active":
      color = "good";
      emoji = "🎉";
      title = "Subscription Activated";
      fields = [
        { title: "Customer", value: event.customer.email, short: true },
        { title: "Product ID", value: event.product_id, short: true },
        { title: "Amount", value: `$${(event.recurring_pre_tax_amount / 100).toFixed(2)}/${event.payment_frequency_interval}`, short: true },
        { title: "Next Billing", value: new Date(event.next_billing_date).toLocaleDateString(), short: true }
      ];
      break;
      
    case "subscription.cancelled":
      color = "warning";
      emoji = "⚠️";
      title = "Subscription Cancelled";
      fields = [
        { title: "Customer", value: event.customer.email, short: true },
        { title: "Product ID", value: event.product_id, short: true },
        { title: "Cancellation Date", value: new Date(event.cancelled_at).toLocaleDateString(), short: true },
        { title: "Cancel at Next Billing", value: event.cancel_at_next_billing_date ? "Yes" : "No", short: true }
      ];
      break;
      
    case "refund.succeeded":
      color = "good";
      emoji = "💰";
      title = "Refund Processed";
      fields = [
        { title: "Amount", value: `$${(event.amount / 100).toFixed(2)}`, short: true },
        { title: "Refund ID", value: event.refund_id, short: true },
        { title: "Payment ID", value: event.payment_id, short: true },
        { title: "Reason", value: event.reason || "Not specified", short: true }
      ];
      break;
      
    case "dispute.opened":
      color = "danger";
      emoji = "🚨";
      title = "New Dispute Opened";
      fields = [
        { title: "Payment ID", value: event.payment_id, short: true },
        { title: "Amount", value: `$${(event.amount / 100).toFixed(2)}`, short: true },
        { title: "Status", value: event.dispute_status, short: true },
        { title: "Stage", value: event.dispute_stage, short: true },
        { title: "Remarks", value: event.remarks || "No remarks", short: false }
      ];
      break;
      
    case "license_key.created":
      color = "good";
      emoji = "🔑";
      title = "License Key Created";
      fields = [
        { title: "License ID", value: event.id, short: true },
        { title: "Product ID", value: event.product_id, short: true },
        { title: "License Key", value: event.key.substring(0, 8) + "...", short: true },
        { title: "Expires", value: event.expires_at ? new Date(event.expires_at).toLocaleDateString() : "Never", short: true }
      ];
      break;
      
    default:
      // Handle any other events with a generic format
      color = "warning";
      emoji = "ℹ️";
      title = webhook.eventType.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
      fields = [
        { title: "Event Type", value: webhook.eventType, short: true },
        { title: "Timestamp", value: timestamp, short: true }
      ];
  }
  
  webhook.payload = {
    attachments: [{
      color: color,
      title: `${emoji} ${title}`,
      fields: fields,
      footer: "Dodo Payments",
      ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
    }]
  };

  return webhook;
}
```

## Best Practices

To make your Slack notifications effective:

* Use rich message attachments with colors, fields, and formatting for clarity and actionability.
* Always include key data such as amounts, customer emails, and IDs for quick identification.
* Choose colors that match the event type: green (`good`) for success, red (`danger`) for disputes or failures, yellow (`warning`) for cancellations, and blue (`#36a64f`) for informational events.
* Add timestamps to help track when each event occurred.

<Warning>
  **Handle Sensitive Data**: Be careful not to include sensitive information like full license keys or personal data in Slack messages. Consider truncating or masking sensitive values.
</Warning>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Notifications not appearing in Slack">
    * Verify that the Slack webhook URL is correct and active
    * Check that the transformation code is valid JavaScript
    * Ensure the selected event types are being triggered
    * Verify that your Slack app has the necessary permissions
  </Accordion>

  <Accordion title="Transformation errors">
    * Check the webhook management portal for transformation error logs
    * Verify that the webhook payload structure matches your transformation code
    * Test your transformation code with sample data
    * Ensure all required fields are present in the webhook payload
  </Accordion>

  <Accordion title="Missing event types">
    * Confirm that the events you want to receive are enabled in your Dodo Payments webhook configuration
    * Check that the event types are selected in your Slack connector configuration
    * Verify that your endpoint is properly configured to receive the events
  </Accordion>
</AccordionGroup>
