
Share:
A trained actor with a dissertation on standup comedy, I came into PHP development via the meetup scene. You can find me speaking and writing on tech, or playing/buying odd records from my vinyl collection.
Receiving an SMS with PHP and Vonage
Time to read: 4 minutes
I would say the most commonly asked question I get is about sending and receiving SMS texts using a backend or framework. The good news here is that you can accomplish SMS functionality in your app (be it Symfony, Laravel, or Drupal) in relatively few lines of code. Previously, I have written about how to send an SMS in PHP, so in this tutorial, we will learn how to wire up your app to read incoming SMS Webhooks with Slim PHP when the end device replies.
Prerequisites
PHP 8.2+
Node 22+
A Vonage Account
Create Your Slim Application
Firstly, you will need to create a new Composer project, then fetch Slim.
mkdir recieving-sms && cd recieving-sms
composer initFollow the interactive CLI instructions, and you can use the defaults for everything except choosing your packages interactively. You should now have a composer.json file: in my case, it looks like this:
Now, we add Slim, Slim’s PSR-7 compatible HTTP handling, and the Vonage PHP SDK:
composer require slim/slim
composer require slim/psr7
composer require vonage/client-core Adding Our Route

The incoming SMS will be configured to take the form of a POST request with the data in a JSON body. We need to set this up in Slim accordingly, so we need to create the entry point to our app.
touch src/index.phpAnd then add our code into the new file:
<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
use Slim\Factory\AppFactory;
require 'vendor/autoload.php';
$app = AppFactory::create();
$handler = function (Request $request, Response $response) {
return $response->withStatus(204);
};
$app->map(['POST'], '/webhooks/sms', $handler);
$app->run();We now have an open POST route that responds with HTTP 204. This signals back to Vonage that the webhook has been successfully received. Now we want to hydrate the Webhook into a PHP SDK object and write it to a new log file. We’re going to use Monolog for this:
composer require monolog/monologNext, we implement hydrating the Webhook and writing it to our log file in the $handler:
<?php
use Monolog\Level;
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
use Slim\Factory\AppFactory;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
require 'vendor/autoload.php';
$app = AppFactory::create();
$logger = new Logger('sms');
$logger->pushHandler(new StreamHandler(__DIR__ . '/../log.txt', Level::Info));
$handler = function (Request $request, Response $response) use ($logger) {
$sms = \Vonage\Messages\Webhook\Factory::createFromArray($request->getBody());
$logger->info('Message Received' . $sms->toArray());
return $response->withStatus(204);
};The app is ready to go; run it using PHP’s built-in web server:
php -S 127.0.0.1:8000 -t src/ Installing the Vonage CLI
Using a JavaScript Package Manager such as npm or yarn, install the Vonage CLI globally:
npm install -g @vonage/cliTwo configurations are now required: set up your API keys with ngrok as part of the setup process, and follow the Vonage setup instructions for the Vonage CLI.
Adding a Vonage Number
We’re going to use the Vonage CLI to make the process slightly easier. Head to the Vonage Dashboard and get your API Key and Secret.
Once you have your API credentials, follow the README in the CLI source code to set it up.
Now use the CLI to view available numbers for purchase:
vonage numbers search usA list of available numbers will show, so you can then opt to purchase one.
vonage numbers buy <number> Wiring It All Together
Our last steps are to create an application in the CLI and attach the number to it. Once that’s done, you can send a message to that number, and the webhook will be fired to your app.
Firstly, create the app:
vonage apps create "My App"Next, give it Messages capability:
vonage apps capabilities update <your-app-id> messages \
--messages-inbound-url=https://example.com/webhooks/inbound \
--messages-status-url=https://example.com/webhooks/statusWe’ve added example.com as a placeholder for now, because the CLI will handle our domains as you’ll see later.
We add the number to the application:Using the Vonage Tunnel
vonage apps numbers link <your-app-id> 07730006666 Using the Vonage Tunnel

You will need to expose your Slim application to the outside world so that Vonage is able to send you WebHooks. To do this, you will need to install ngrok. However, instead of using ngrok alone, the Vonage CLI has some useful tooling that wraps around it, making the developer experience a bit more frictionless.
You can use the tunnel feature to open your app up to receive WebHooks with the following command:
vonage tunnel ngrok <your-app-id>What this command does is pretty useful. Instead of just telling ngrok to serve your application, it runs some update commands on your application instance to change the existing domain for webhooks (in our case, https://example.com) to the ngrok-generated domain it has run in the background (e.g., https://3d3daF.ngrok.com). After the domain, it stitches together the existing relative paths in the application, so in our case, /webhooks/inbound and /webhooks/status. When you quit the tunnel, it also attempts to reset them to their previous value https://example.com in our case).
All the pieces are in place: take your mobile device and send an SMS to your application number. Watch as your app receives a Webhook and populates the log.
Conclusion
It’s pretty apparent that it doesn’t take many lines of code to boot an application that can receive an SMS, just like sending one doesn’t take many lines of code either. When it comes to scaling, however, you’ll want to use more robust monitoring when your application is sending and receiving thousands of requests; you might want to take a look at monitoring application activity with Nightwatch for something like this.
Have a question or want to share what you're building?
Subscribe to the Developer Newsletter
Follow us on X (formerly Twitter) for updates
Watch tutorials on our YouTube channel
Connect with us on the Vonage Developer page on LinkedIn
Help us improve our developer experience by filling out our Voice of the Developer Feedback
Stay connected and keep up with the latest developer news, tips, and events.