Back to Blog
Developers

Slack API in PHP: Plain curl vs jolicode/slack-php-api (Tested Code)

Two tested ways to call the Slack API from PHP: plain curl with a bot token, and the jolicode/slack-php-api client. We ran both on PHP 8.5 on 5 November 2026, posted a message, read history and caught a bad channel ID. Code and output below.

Slack Green Team
November 5, 2026
November 5, 2026
3 min read
Share:
slack
slack api
php

To use the Slack API from PHP, send an HTTPS request with a bot token to a method such as https://slack.com/api/chat.postMessage, either with PHP's curl functions or with jolicode/slack-php-api, the PHP client Slack lists among its community tools. Slack has no official PHP SDK. On 5 November 2026 we ran both on PHP 8.5.12 with Composer 2.11.1 against a test workspace: posted a message, read the channel history with a cursor and sent to a channel that does not exist. The scripts and their real output are below.

Which PHP package to use

We read the main packages on Packagist on 5 November 2026:

PackageLatest releaseDownloadsWhat it covers
jolicode/slack-php-apiv4.10.0, 2026-09-255,389,209The whole Web API, generated from Slack's spec
alek13/slack2.4.0, 2026-08-076,245,105Incoming webhooks only (a maintained fork of maknz/slack)
maknz/slack1.7.0, 2015-06-0312,324,526Incoming webhooks only, no release since 2015
slack-php/slack-app-framework1.0.0, 2022-02-2435,417A Bolt-style app framework, no release since 2022

For one-way alerts into one channel, an incoming webhook needs no package at all; our webhook curl examples work the same from PHP's curl. For anything that reads, replies or picks the channel per message, use a bot token as below.

Setup

Create a Slack app with a bot user and the scopes chat:write and channels:history, install it, and copy the Bot User OAuth Token (xoxb-); our Slack bot token guide shows where it is. Invite the bot to the channel. Then, for the client:

composer require jolicode/slack-php-api symfony/http-client nyholm/psr7

The client does not bring its own HTTP library. It needs a PSR-18 HTTP client and PSR-7 messages, which is what the two extra packages are.

1. Plain curl

<?php
$ch = curl_init('https://slack.com/api/chat.postMessage');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('SLACK_BOT_TOKEN'),
        'Content-Type: application/json; charset=utf-8',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'channel' => getenv('SLACK_CHANNEL'),
        'text' => 'Hello from PHP (curl)',
    ]),
]);
$res = json_decode(curl_exec($ch), true);
echo $res['ok'] ? "ok ts={$res['ts']}\n" : "error: {$res['error']}\n";

Never appear "away" on Slack again

Cloud-based. No downloads. Works 24/7 even when your laptop is off.

2. jolicode/slack-php-api

<?php
require __DIR__ . '/vendor/autoload.php';

use JoliCode\Slack\ClientFactory;
use JoliCode\Slack\Exception\SlackErrorResponse;

$client = ClientFactory::create(getenv('SLACK_BOT_TOKEN'));
$channel = getenv('SLACK_CHANNEL');

$msg = $client->chatPostMessage(['channel' => $channel, 'text' => 'Hello from PHP (jolicode/slack-php-api)']);
echo 'posted ts=' . $msg->getTs() . "\n";

$history = $client->conversationsHistory(['channel' => $channel, 'limit' => 2]);
foreach ($history->getMessages() as $m) {
    echo '  history: ' . $m->getTs() . ' ' . $m->getText() . "\n";
}
echo '  next_cursor: ' . ($history->getResponseMetadata()?->getNextCursor() ?: '(none)') . "\n";

try {
    $client->chatPostMessage(['channel' => 'C000BAD', 'text' => 'x']);
} catch (SlackErrorResponse $e) {
    echo get_class($e) . ': ' . $e->getErrorCode() . "\n";
}

The output

We ran the curl script twice, the second time with the channel set to C000BAD, then the client script:

--- curl
ok ts=1793864866.824929
--- curl bad channel
error: channel_not_found
--- jolicode
posted ts=1793864867.220519
  history: 1793864867.220519 Hello from PHP (jolicode/slack-php-api)
  history: 1793864866.824929 Hello from PHP (curl)
  next_cursor: bmV4dF90czoxNzkzODY0NzI1MzcyMzE5
JoliCode\Slack\Exception\SlackErrorResponse: channel_not_found

Both posts arrived from the bot, one under the other:

Slack channel with two messages from the test bot: Hello from PHP (curl) and Hello from PHP (jolicode/slack-php-api)

The two styles report errors differently. Slack answers a bad call with HTTP 200 and "ok": false, which plain curl hands to you as data, so your code has to check ok every time. The jolicode client turns the same answer into a SlackErrorResponse exception, and getErrorCode() gives the Slack error string. If the error is missing_scope, our missing_scope guide explains the fix.

The client also returns typed objects: getTs() on the posted message, getMessages() on the history, and getResponseMetadata()->getNextCursor() for the next page. Pass that value as cursor in the next conversationsHistory call until it comes back empty, as in our guide to getting messages from a channel.

Things that tripped us up

  • • Method names follow Slack's with the dot removed and camel case: chat.postMessage is chatPostMessage, conversations.history is conversationsHistory.
  • • Arguments go in as an array with Slack's own field names (channel, text, limit, cursor), not as PHP named arguments.

FAQ

Is there an official Slack SDK for PHP?

No. Slack's official SDKs cover Python, Node.js and Java. Slack's list of community tools names jolicode/slack-php-api for the Web API.

Can I verify Slack requests in PHP without a package?

Yes. Slack signs each request with your signing secret; compare hash_hmac('sha256', "v0:$timestamp:$body", $secret) with the X-Slack-Signature header using hash_equals. Our Slack signing secret guide covers the details.

Always Active

Stop Jiggling Your Mouse.

Join hundreds of remote workers who never worry about their Slack status. Set it up once, stay green forever.

Related Articles

Developers

Slack API in C#: HttpClient vs SlackNet, With Tested .NET 10 Code

Slack has no official .NET SDK. We posted to Slack from C# two ways on .NET 10 on 5 November 2026: plain HttpClient with System.Text.Json, and the SlackNet package with a Block Kit section. Both versions, their real output and how each reports a bad channel.

Slack Green Team
Developers

Slack Notifications From Rails: slack-notifier, slack-ruby-client and Net::HTTP Tested

Three ways to post to Slack from Rails, run on Ruby 3.4 and Rails 8.1 on 5 November 2026: plain Net::HTTP to a webhook, the slack-notifier gem (last release 2021, still works), and slack-ruby-client with a bot token. Plus exception_notification sending a real error to Slack.

Slack Green Team
Developers

Sign in with Slack (OpenID Connect): A Tested Python Example

Sign in with Slack is OpenID Connect on top of OAuth 2.0: send the user to slack.com/openid/connect/authorize, swap the code at openid.connect.token, and check the RS256 id_token. We ran the whole flow on 5 November 2026 and show the real claims and errors.

Slack Green Team