PHP SDK
composer require vaartix/vaartix-phpThe current version is 0.3.0. Works with PHP 8.1 and later, with the standard curl and json extensions and no other
dependencies. The package is on Packagist and
the source is on GitHub at vaartix-mail/vaartix-php.
Step-by-step guides: Laravel and Symfony.
Using an AI assistant such as Claude or Cursor? The MCP server lets it send email and look up delivery status through the same API, without writing code.
Send an email
Section titled “Send an email”use Vaartix\Vaartix;
$vaartix = new Vaartix(); // reads the VAARTIX_API_KEY environment variable
$email = $vaartix->emails->send([ 'subject' => 'Hello from Vaartix', 'html' => '<strong>It works!</strong>',]);
echo $email['id']; // em_...Keys can be snake_case (reply_to, scheduled_at) or the API’s camelCase (replyTo,
scheduledAt). Responses are the API’s JSON as arrays, exactly as in the
API reference.
Methods
Section titled “Methods”// Retry safely: the same key within 24 hours returns the first email instead of sending twice.$vaartix->emails->send($email, idempotencyKey: "welcome-{$user->id}");
// Send later (up to 30 days ahead), and cancel if plans change.$scheduled = $vaartix->emails->send([...$email, 'scheduled_at' => '2026-11-01T09:00:00+05:30']);$vaartix->emails->cancel($scheduled['id']);
// Up to 100 emails in one request.$vaartix->batch->send([$email1, $email2]);
// Look up an email and its delivery events, or list recent bounces.$vaartix->emails->get('em_...');$vaartix->emails->list(['status' => 'bounced', 'days' => 7]);No domain yet? Send from any address at test.vaartix.com to delivered@, bounced@ or
[email protected] to simulate what happens:
$vaartix->emails->send([ 'subject' => 'Hello', 'text' => 'It works!',]);Errors
Section titled “Errors”API and network errors throw Vaartix\Exceptions\VaartixException:
use Vaartix\Exceptions\VaartixException;
try { $vaartix->emails->send($email);} catch (VaartixException $e) { echo $e->type, ' ', $e->statusCode, ' ', $e->getMessage(); // e.g. rate_limited 429 Too many requests...}$e->type is a stable code; the full list is in Errors. Network failures
have type === 'network_error' and statusCode === null.
Laravel
Section titled “Laravel”Since vaartix/vaartix-php 0.2.0, the package registers a vaartix mail driver automatically
(Laravel 12 and 13), so Laravel’s Mail facade, Mailables, notifications and queued mail all go
through Vaartix.
MAIL_MAILER=vaartixVAARTIX_API_KEY=vx_live_...VAARTIX_WEBHOOK_SECRET=whsec_...'vaartix' => [ 'key' => env('VAARTIX_API_KEY'), 'webhook_secret' => env('VAARTIX_WEBHOOK_SECRET'),],'vaartix' => [ 'transport' => 'vaartix',],That’s all. Existing code keeps working:
Mail::to($user)->send(new OrderConfirmed($order));Laravel’s ->tag('welcome') and ->metadata('order_id', 42) become Vaartix tags, so you can
filter by them in the dashboard. SentMessage::getMessageId() returns the Vaartix email ID.
To call the API directly, inject the client; it’s registered as a singleton from
services.vaartix.key:
public function store(Request $request, \Vaartix\Vaartix $vaartix){ $vaartix->emails->send([ 'to' => $request->user()->email, 'subject' => 'Your order is confirmed', 'html' => view('emails.order-confirmed', ['order' => $order])->render(), ], idempotencyKey: "order-confirmed-{$order->id}");}Symfony Mailer
Section titled “Symfony Mailer”Since vaartix/vaartix-php 0.3.0, Symfony Mailer can use Vaartix through a MAILER_DSN. Set the DSN
and register the transport factory once:
MAILER_DSN=vaartix+api://vx_your_api_key@defaultservices: Vaartix\Symfony\VaartixTransportFactory: parent: mailer.transport_factory.abstract tags: ['mailer.transport_factory']default means https://api.vaartix.com. Add ?timeout=10 to change the request timeout
(seconds). If your key contains + or /, URL-encode them in the DSN. Step by step:
Symfony guide.
Webhooks
Section titled “Webhooks”Check that a webhook request really came from Vaartix before trusting it. Webhook::verify() checks
the signature and timestamp (Standard Webhooks) and returns the
parsed event. Pass the raw body, not parsed JSON.
Plain PHP
Section titled “Plain PHP”use Vaartix\Webhook;use Vaartix\Exceptions\WebhookVerificationException;
try { $event = Webhook::verify(file_get_contents('php://input'), getallheaders(), getenv('VAARTIX_WEBHOOK_SECRET'));} catch (WebhookVerificationException $e) { http_response_code(400); exit;}Laravel
Section titled “Laravel”Exclude this route from CSRF protection; Vaartix signs the request instead.
use Illuminate\Http\Request;use Vaartix\Webhook;use Vaartix\Exceptions\WebhookVerificationException;
Route::post('/webhooks/vaartix', function (Request $request) { try { $event = Webhook::verify($request->getContent(), $request->headers->all(), config('services.vaartix.webhook_secret')); } catch (WebhookVerificationException $e) { abort(400); } if ($event['type'] === 'email.bounced') { // stop emailing $event['data']['recipient'] } return response()->noContent();});Manage endpoints with $vaartix->webhooks->create(), list(), get(), update(), remove(),
rotateSecret(), deliveries() and retryDelivery(). See Webhooks for
the events and how retries work.