Slack

Overview

The Slack notification feature allows you to send messages directly to your end-users’ Slack workspaces. Integrate Slack with Pingram to send notifications directly to your users’ Slack channels. This guide will help you connect your Slack workspace and set up frontend integration for various frameworks.

Requirements

  • A Slack workspace
  • Access to Pingram

Step 1: Integrate Frontend

Redirect users to Slack OAuth, then optionally let them pick a channel.

There are two ways to do this:

Install the SDK:

npm install @notificationapi/react

Add our provider and SlackConnect component anywhere in your front-end:

import { NotificationAPIProvider, SlackConnect } from '@notificationapi/react';

const SettingsPage = () => {
  return (
    <NotificationAPIProvider clientId="YOUR_CLIENT_ID" userId="USER_ID">
      <SlackConnect />
    </NotificationAPIProvider>
  );
};

For custom UIs, use our headless JavaScript library. Install the SDK:

npm install @notificationapi/core

Generate the OAuth URL and redirect the user to it:

import { NotificationAPIClientSDK } from '@notificationapi/core';

// Initialize
const client = NotificationAPIClientSDK.init({
  clientId: 'YOUR_CLIENT_ID',
  userId: 'USER_ID'
});

// Generate OAuth URL (redirects back to current page by default)
const oauthUrl = client.slack.getOAuthUrl();
window.location.href = oauthUrl;

Read workspace channels and users:

const user = await client.user.get();
if (user.slackToken) {
  const response = await client.slack.getChannels();
}

Set a default channel/user for notifications to go to:

await client.slack.setChannel(`#${channelName}`);
await client.slack.setChannel(`@${userName}`);

Tenants

To avoid multiple users from one organization creating multiple “integrations” to the same channel like #general, it’s best that you set the “userId” to the end-user’s organization ID. This way, multiple users would be seeing and updating the same Slack integration.

At send time, you would also use the orgId.

Default Channel

You can start sending right after OAuth, by specifying the slackChannel parameter in the send method. The channel selection simply let’s the user pick a default one, so you don’t have to figure out the slackChannel in your back-end.

Step 2: Trigger Notifications from Backend

This part is easy, same as any other channel:

Install the SDK:

npm install pingram

Import, initialize, and send:

import { Pingram } from 'pingram';

const pingram = new Pingram({
  apiKey: 'Your api key here'
});

pingram.send({
  type: 'order_tracking',
  to: {
    id: 'USER_ID or ORG_ID', // MUST match the userId from Step 1
    slackChannel: '#general' // Optional. If not specified, the default channel will be used
  },
  slack: {
    text: 'Hello, world!', // supports plain text and blocks
    blocks: [
      { type: 'section', text: { type: 'mrkdwn', text: 'Hello, *world*!' } }
    ]
  }
});

Install the SDK:

pip install pingram-python

Import, initialize, and send:

import asyncio
from pingram import Pingram

async def send_slack_notification():
    async with Pingram(api_key="pingram_sk_...") as client:
        await client.send({
            "type": "order_tracking",
            "to": {
                "id": "USER_ID or ORG_ID",  # MUST match the userId from Step 1
                "slackChannel": "#general"  # Optional. If not specified, the default channel will be used
            },
            "slack": {
                "text": "Hello, world!"
            }
        })

# Run the async function
asyncio.run(send_slack_notification())

Install the SDK:

composer require pingram/php

Import, initialize, and send:

use Pingram\Client;
use Pingram\Model\SenderPostBody;

$client = new Client('pingram_sk_...');

$body = new SenderPostBody([
    'type' => 'order_tracking',
    'to' => [
        'id' => 'USER_ID or ORG_ID',  // MUST match the userId from Step 1
        'slackChannel' => '#general'   // Optional. If not specified, the default channel will be used
    ],
    'slack' => [
        'text' => 'Hello, world!'  // supports plain text and blocks
    ]
]);
$client->send($body);

Install the SDK:

composer require notificationapi/notificationapi-laravel-server-sdk:@dev

Setup and send:

Add to .env:

NOTIFICATION_API_KEY=clientID
NOTIFICATION_API_SECRET=clientSecret

Send notification:

$user = new NotificationUser();
$user->id = "USER_ID or ORG_ID"; // MUST match the userId from Step 1

$user->notify(new MyNotification([
    "type" => "order_tracking",
    "slack" => [
        "text" => "Hello, world!", // supports plain text and blocks
        "blocks" => List.of(new Block(BlockType.SECTION, Map.of("text", Map.of("type", "mrkdwn", "text", "Hello, *world*!"))))
    ]
]));

To specify a channel:

$user = new NotificationUser();
$user->id = "USER_ID or ORG_ID";
$user->slackChannel = "#general";

$user->notify(new MyNotification([
    "type" => "order_tracking",
    "slack" => [
        "text" => "Hello, world!", # supports plain text and blocks
        "blocks" => List.of(new Block(BlockType.SECTION, Map.of("text", Map.of("type", "mrkdwn", "text", "Hello, *world*!"))))
    ]
]));

Install the SDK:

go get github.com/pingram-io/pingram-go

Import, initialize, and send:

package main

import (
    "context"
    "log"

    pingram "github.com/pingram-io/pingram-go"
)

func main() {
    client := pingram.NewClient("pingram_sk_...") // Your secret API key

    slack := pingram.NewSenderPostBodySlack("Hello, world!")
    slack.SetBlocks([]map[string]interface{}{
        {"type": "section", "text": map[string]interface{}{"type": "mrkdwn", "text": "Hello, *world*!"}},
    })

    body := pingram.SenderPostBody{
        Type: pingram.PtrString("order_tracking"),
        User: &pingram.GetUsersResponseUsersInner{
            Id:           "USER_ID or ORG_ID", // MUST match the userId from Step 1
            SlackChannel: pingram.PtrString("#general"), // Optional. If not specified, the default channel will be used
        },
        Slack: slack,
    }

    _, _, err := client.DefaultAPI.Send(context.Background()).SenderPostBody(body).Execute()
    if err != nil {
        log.Fatal(err)
    }
}

Install the SDK:

dotnet add package Pingram

Import, initialize, and send:

using Pingram;
using Pingram.Model;

var client = new PingramClient("your_api_key");
var body = new SenderPostBody
{
    Type = "order_tracking",
    To = new SenderPostBodyTo { Id = "USER_ID or ORG_ID", SlackChannel = "#general" }, // MUST match the userId from Step 1
    Slack = new SenderPostBodySlack { Text = "Hello, world!" } // supports plain text and blocks
};
await client.SendAsync(body);

Add the Pingram dependency to your pom.xml. Check Maven Central for the latest version.

<dependencies>
    <dependency>
        <groupId>io.pingram</groupId>
        <artifactId>pingram</artifactId>
        <version>0.1.0</version>
    </dependency>
</dependencies>

Import, initialize, and send:

package com.example;

import io.pingram.Pingram;
import io.pingram.model.*;

public class Example {
    public static void main(String[] args) {
        Pingram pingram = new Pingram("pingram_sk_..."); // Your secret API key

        SenderPostBodyTo to = new SenderPostBodyTo()
            .id("USER_ID or ORG_ID") // MUST match the userId from Step 1
            .slackChannel("#general"); // Optional. If not specified, the default channel will be used

        SenderPostBody body = new SenderPostBody()
            .type("order_tracking")
            .to(to)
            .slack(new SenderPostBodySlack()
                .text("Hello, world!") // supports plain text and blocks
            );

        SenderPostResponse response = pingram.send(body);
        System.out.println("Tracking ID: " + response.getTrackingId());
    }
}

Install with gem install pingram, then import, initialize, and send:

require 'pingram'

client = Pingram::Client.new(api_key: 'pingram_sk_...')
body = Pingram::SenderPostBody.new(
  type: 'order_tracking',
  to: { id: 'USER_ID or ORG_ID', slack_channel: '#general' },
  slack: { text: 'Hello, world!', blocks: [{ type: 'section', text: { type: 'mrkdwn', text: 'Hello, *world*!' } }] }
)
client.send(body)
INFO

The slackChannel parameter accepts #channelName, channelName (without #), channel ID, user ID, and @username.


How it Works (Diagram)

sequenceDiagram participant User participant Your Frontend participant Slack participant Your Backend participant Pingram Note over User,Pingram: Step 1: Integrate Slack User->>Your Frontend: Clicks "Connect Slack" Your Frontend-->>Slack: Redirects to Slack OAuth User->>Slack: Authorizes Slack app Slack-->>Your Frontend: Redirects to channel picker User->>Your Frontend: Selects channel Your Frontend-->>Pingram: Stores channel preference Note over User,Pingram: Step 2: Trigger Notifications Your Backend->>Pingram: Triggers notification Pingram->>Slack: Delivers to user's channel

Frequently Asked Questions (FAQs)

Does the user see Pingram branding during the Slack authorization process?

No. All parts of the process are bland and generic with no branding.

Can I use my own Slack app?

Yes. Reach out to our team to learn more.