PHP SDK
The official PHP SDK for Veil Mail with idiomatic PHP patterns.
- Exception-based error handling
- PSR-4 autoloading via Composer
- Constant-time HMAC webhook verification
- Zero external dependencies (cURL only)
- PHP 8.1+ with readonly properties and named arguments
Installation
composer require veilmail/veilmail-phpQuick Start
send.php
<?php
require_once 'vendor/autoload.php';
$client = new VeilMail\VeilMail('veil_live_xxxxx');
$email = $client->emails->send([
'from' => 'hello@yourdomain.com',
'to' => 'user@example.com',
'subject' => 'Hello from PHP!',
'html' => '<h1>Welcome!</h1>',
]);
echo $email['id']; // email_xxxxx
echo $email['status']; // queuedResources
The client exposes the same resources as the Node.js SDK:
| Resource | Description |
|---|---|
$client->emails | Send, batch send, list, get, cancel, update emails |
$client->domains | Create, verify, update, list, delete domains |
$client->templates | Create, update, preview, list, delete templates |
$client->audiences | Manage audiences and subscribers |
$client->campaigns | Create, schedule, send, pause, resume, cancel campaigns |
$client->webhooks | Manage webhook endpoints, test, rotate secrets |
$client->topics | Manage subscription topics and preferences |
$client->properties | Manage contact property definitions and values |
Sending Emails
emails.php
// Send with template
$email = $client->emails->send([
'from' => 'hello@yourdomain.com',
'to' => 'user@example.com',
'templateId' => 'tmpl_xxx',
'templateData' => ['name' => 'Alice'],
]);
// Send with attachments
$email = $client->emails->send([
'from' => 'hello@yourdomain.com',
'to' => 'user@example.com',
'subject' => 'Invoice',
'html' => '<p>Attached is your invoice.</p>',
'attachments' => [
[
'filename' => 'invoice.pdf',
'content' => $base64Content,
'contentType' => 'application/pdf',
],
],
]);
// Batch send (up to 100)
$result = $client->emails->sendBatch([
['from' => 'hi@yourdomain.com', 'to' => ['u1@ex.com'], 'subject' => 'Hi', 'html' => '<p>Hi!</p>'],
['from' => 'hi@yourdomain.com', 'to' => ['u2@ex.com'], 'subject' => 'Hi', 'html' => '<p>Hi!</p>'],
]);Subscriber Management
subscribers.php
$subs = $client->audiences->subscribers('audience_xxxxx');
// Add a subscriber
$subscriber = $subs->add([
'email' => 'user@example.com',
'firstName' => 'Alice',
'lastName' => 'Smith',
'consentType' => 'express',
]);
// List subscribers
$result = $subs->list(['status' => 'active', 'limit' => 50]);
foreach ($result['data'] as $sub) {
echo $sub['email'] . "\n";
}
// Import from CSV
$result = $subs->import(['csvData' => "email,firstName\nuser@example.com,Bob"]);
echo "Created: {$result['created']}, Skipped: {$result['skipped']}";
// Export as CSV
$csv = $subs->export(['status' => 'active']);Error Handling
errors.php
use VeilMail\Exceptions\RateLimitException;
use VeilMail\Exceptions\PiiDetectedException;
use VeilMail\Exceptions\ValidationException;
use VeilMail\Exceptions\AuthenticationException;
use VeilMail\Exceptions\VeilMailException;
try {
$client->emails->send([
'from' => 'hello@yourdomain.com',
'to' => 'user@example.com',
'subject' => 'Hello',
'html' => '<p>Hi!</p>',
]);
} catch (RateLimitException $e) {
echo "Rate limited. Retry after {$e->getRetryAfter()}s";
} catch (PiiDetectedException $e) {
echo "PII detected: " . implode(', ', $e->getPiiTypes());
} catch (ValidationException $e) {
echo "Validation error: {$e->getMessage()}";
} catch (AuthenticationException $e) {
echo "Invalid API key";
} catch (VeilMailException $e) {
echo "API error: {$e->getMessage()} (code: {$e->getErrorCode()})";
}Webhook Verification
Use the built-in utility to verify webhook signatures:
webhook.php
$body = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_SIGNATURE_HASH'] ?? '';
if (!VeilMail\Webhook::verifySignature($body, $signature, $webhookSecret)) {
http_response_code(401);
exit;
}
$event = json_decode($body, true);
switch ($event['type']) {
case 'email.delivered':
// Handle delivery
break;
case 'email.bounced':
// Handle bounce
break;
}
http_response_code(200);Laravel Integration
Example webhook controller for Laravel:
WebhookController.php
use Illuminate\Http\Request;
class WebhookController extends Controller
{
public function handle(Request $request)
{
$body = $request->getContent();
$signature = $request->header('X-Signature-Hash', '');
$secret = config('services.veilmail.webhook_secret');
if (!\VeilMail\Webhook::verifySignature($body, $signature, $secret)) {
return response('Unauthorized', 401);
}
$event = $request->json()->all();
match ($event['type']) {
'email.delivered' => $this->handleDelivered($event),
'email.bounced' => $this->handleBounced($event),
default => null,
};
return response('OK', 200);
}
}Required Scopes
The PHP SDK uses the same API scopes as the Authentication system. See the Node.js SDK documentation for the full scope reference.