SMS Transport API

July 11, 2026 ยท View on GitHub

Reference for implementing a custom SMS transport.

For the basic SMS OTP setup (configuration, controller actions, phone enrollment) see sms_verification.md.


TransportInterface

Every SMS transport must implement CakeVerification\Transport\Sms\TransportInterface:

namespace CakeVerification\Transport\Sms;

interface TransportInterface
{
    public function send(Message $message): Result;
}

Message

PropertyTypeDescription
$recipientstringDestination phone number (E.164 recommended)
$bodystringFull message text including the OTP code
$senderstring|nullSender ID or number (optional)

Result

PropertyTypeDescription
$successbooltrue if the message was accepted by the provider
$errorstring|nullError description on failure
$messageMessage|nullThe original message
$providerIdstring|nullProvider-assigned message ID
$statusCodeint|nullHTTP or provider status code
$retryAfterint|nullSeconds to wait before retrying (rate-limit hint)

Implementing a custom transport

namespace App\Sms;

use CakeVerification\Transport\Sms\Message;
use CakeVerification\Transport\Sms\Result;
use CakeVerification\Transport\Sms\TransportInterface;

class TwilioTransport implements TransportInterface
{
    public function __construct(private array $options = []) {}

    public function send(Message $message): Result
    {
        $result = new Result();

        // call Twilio API with $message->recipient and $message->body ...

        $result->success = true;
        $result->providerId = 'twilio-message-id';

        return $result;
    }
}

If the transport constructor requires no arguments, it is instantiated directly. If it requires one argument, the options array from the transport config is passed.


Registering the transport

// config/verification.php
'sms' => [
    'defaultTransport' => 'twilio',
    'transports' => [
        'twilio' => [
            'className' => \App\Sms\TwilioTransport::class,
            'options'   => [
                'sid'   => env('TWILIO_SID'),
                'token' => env('TWILIO_TOKEN'),
                'from'  => env('TWILIO_FROM'),
            ],
        ],
    ],
],

DummyTransport (development)

The plugin ships a DummyTransport that logs the message and stores it in the CakePHP default cache instead of sending a real SMS. Use it during development:

'sms' => [
    'defaultTransport' => 'dummy',
],

VerificationHelper::lastSmsCode() reads the cached message and returns the numeric code โ€” convenient for checking the OTP without a real phone. See ../verification_helper.md.


Documentation

Full documentation index: ../index.md