PHPackages                             sendpigeon/sdk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Mail &amp; Notifications](/categories/mail)
4. /
5. sendpigeon/sdk

ActiveLibrary[Mail &amp; Notifications](/categories/mail)

sendpigeon/sdk
==============

Official PHP SDK for SendPigeon - Transactional Email API

v0.4.0(4mo ago)00MITPHPPHP &gt;=8.1

Since Dec 28Pushed 4mo agoCompare

[ Source](https://github.com/sendpigeon/sdk-php)[ Packagist](https://packagist.org/packages/sendpigeon/sdk)[ Docs](https://sendpigeon.dev)[ RSS](/packages/sendpigeon-sdk/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (2)Versions (3)Used By (0)

SendPigeon PHP SDK
==================

[](#sendpigeon-php-sdk)

Official PHP SDK for [SendPigeon](https://sendpigeon.dev) - Transactional Email API.

Requirements
------------

[](#requirements)

- PHP 8.1+
- Guzzle 7.0+

Installation
------------

[](#installation)

```
composer require sendpigeon/sendpigeon
```

Quick Start
-----------

[](#quick-start)

```
use SendPigeon\SendPigeon;

$client = new SendPigeon('sk_live_xxx');

$response = $client->send(
    to: 'user@example.com',
    subject: 'Hello',
    html: 'Welcome to SendPigeon!'
);

echo "Email sent: " . $response->id;
```

Configuration
-------------

[](#configuration)

```
$client = new SendPigeon(
    apiKey: 'sk_live_xxx',
    baseUrl: 'https://api.sendpigeon.dev',  // Custom base URL
    timeout: 30,                             // Request timeout in seconds
    maxRetries: 2,                           // Retry attempts (max 5)
);
```

Local Development
-----------------

[](#local-development)

Use the SendPigeon CLI to catch emails locally:

```
# Terminal 1: Start local server
npx @sendpigeon-sdk/cli dev

# Terminal 2: Run your app with dev mode
SENDPIGEON_DEV=true php app.php
```

When `SENDPIGEON_DEV=true`, the SDK routes requests to `localhost:4100` instead of production.

Sending Emails
--------------

[](#sending-emails)

### Basic Email

[](#basic-email)

```
$response = $client->send(
    to: 'user@example.com',
    from: 'hello@yourdomain.com',
    subject: 'Welcome!',
    html: 'WelcomeThanks for signing up!',
    text: 'Welcome! Thanks for signing up.',
);
```

### Multiple Recipients

[](#multiple-recipients)

```
$response = $client->send(
    to: ['user1@example.com', 'user2@example.com'],
    subject: 'Team Update',
    html: 'Important update for the team.',
    cc: 'manager@example.com',
    bcc: ['archive@example.com'],
);
```

### With Template

[](#with-template)

```
$response = $client->send(
    to: 'user@example.com',
    templateId: 'tmpl_xxx',
    variables: [
        'name' => 'John',
        'company' => 'Acme Inc',
    ],
);
```

### With Attachments

[](#with-attachments)

```
$response = $client->send(
    to: 'user@example.com',
    subject: 'Your invoice',
    html: 'Please find your invoice attached.',
    attachments: [
        [
            'filename' => 'invoice.pdf',
            'content' => base64_encode(file_get_contents('invoice.pdf')),
        ],
    ],
);
```

### Scheduled Email

[](#scheduled-email)

```
$response = $client->send(
    to: 'user@example.com',
    subject: 'Reminder',
    html: 'Don\'t forget about tomorrow\'s meeting!',
    scheduledAt: '2024-01-15T10:00:00Z',
);
```

### Batch Send (up to 100)

[](#batch-send-up-to-100)

```
$response = $client->sendBatch([
    ['to' => 'user1@example.com', 'subject' => 'Hello', 'html' => 'Hi User 1!'],
    ['to' => 'user2@example.com', 'subject' => 'Hello', 'html' => 'Hi User 2!'],
]);

foreach ($response->data as $result) {
    if ($result->status === 'sent') {
        echo "Email {$result->index} sent: {$result->id}\n";
    }
}
```

### Tracking

[](#tracking)

Enable open/click tracking per email (opt-in):

```
use SendPigeon\Types\TrackingOptions;

$response = $client->send(
    to: 'user@example.com',
    subject: 'Welcome!',
    html: 'Check out our site!',
    tracking: new TrackingOptions(opens: true, clicks: true),
);

// Response may include warnings if tracking is disabled at org level
if ($response->warnings) {
    print_r($response->warnings);
}
```

Configure organization defaults in Settings → Tracking.

Email Management
----------------

[](#email-management)

```
// Get email by ID
$email = $client->emails->get('email_xxx');

// Cancel scheduled email
$cancelled = $client->emails->cancel('email_xxx');
```

Templates
---------

[](#templates)

```
use SendPigeon\Types\Template;

// Create template
$template = $client->templates->create(
    name: 'welcome',
    subject: 'Welcome, {{name}}!',
    html: 'Hello {{name}}Welcome to {{company}}!',
);

// Get template
$template = $client->templates->get('tmpl_xxx');

// List templates
$result = $client->templates->list();

// Update template
$template = $client->templates->update(
    id: 'tmpl_xxx',
    subject: 'Updated subject',
);

// Delete template
$client->templates->delete('tmpl_xxx');
```

Domains
-------

[](#domains)

```
// Add domain
$domain = $client->domains->create('mail.yourdomain.com');

// DNS records are returned for setup
foreach ($domain->dnsRecords as $record) {
    echo "{$record->type} {$record->name} -> {$record->value}\n";
}

// Verify domain
$result = $client->domains->verify('dom_xxx');
if ($result->verified) {
    echo "Domain verified!\n";
}

// List domains
$result = $client->domains->list();

// Delete domain
$client->domains->delete('dom_xxx');
```

API Keys
--------

[](#api-keys)

```
use SendPigeon\Types\ApiKeyMode;
use SendPigeon\Types\ApiKeyPermission;

// Create API key
$key = $client->apiKeys->create(
    name: 'Production',
    mode: ApiKeyMode::Live,
    permission: ApiKeyPermission::FullAccess,
);

// Save $key->key - only returned once!
echo "API Key: " . $key->key;

// List API keys
$result = $client->apiKeys->list();

// Delete API key
$client->apiKeys->delete('key_xxx');
```

Webhook Verification
--------------------

[](#webhook-verification)

```
use SendPigeon\Webhooks;

// In your webhook handler
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$timestamp = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';

$result = Webhooks::verify(
    payload: $payload,
    signature: $signature,
    timestamp: $timestamp,
    secret: 'whsec_xxx',  // Your webhook secret
    maxAge: 300,          // Max age in seconds
);

if (!$result->valid) {
    http_response_code(401);
    echo $result->error;
    exit;
}

// Handle webhook event
$eventType = $result->payload['type'];
switch ($eventType) {
    case 'email.delivered':
        // Handle delivery
        break;
    case 'email.bounced':
        // Handle bounce
        break;
}

http_response_code(200);
```

### Inbound Email Webhooks

[](#inbound-email-webhooks)

```
$result = Webhooks::verifyInbound(
    payload: $payload,
    signature: $signature,
    timestamp: $timestamp,
    secret: 'whsec_inbound_xxx',
);
```

Error Handling
--------------

[](#error-handling)

All methods throw `SendPigeonException` on error:

```
use SendPigeon\Exceptions\SendPigeonException;

try {
    $response = $client->send(
        to: 'user@example.com',
        subject: 'Hello',
    );
} catch (SendPigeonException $e) {
    echo "Error: " . $e->getMessage() . "\n";
    echo "Code: " . $e->errorCode . "\n";      // 'api_error', 'network_error', 'timeout_error'
    echo "API Code: " . $e->apiCode . "\n";    // API-specific code like 'validation_error'
    echo "Status: " . $e->status . "\n";       // HTTP status code
}
```

Idempotency
-----------

[](#idempotency)

Prevent duplicate sends with idempotency keys:

```
$response = $client->send(
    to: 'user@example.com',
    subject: 'Order confirmation',
    html: 'Your order has been confirmed.',
    idempotencyKey: 'order-12345-confirmation',
);
```

License
-------

[](#license)

MIT

###  Health Score

30

—

LowBetter than 64% of packages

Maintenance77

Regular maintenance activity

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity34

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~4 days

Total

2

Last Release

137d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/942e42475a564cb0f73c1cf8a50d38af6842619d0316e85ba81ef6ba7abda5ed?d=identicon)[sendpigeon](/maintainers/sendpigeon)

---

Top Contributors

[![johanstenius](https://avatars.githubusercontent.com/u/20771579?v=4)](https://github.com/johanstenius "johanstenius (8 commits)")

---

Tags

apiemailtransactionalsendpigeon

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/sendpigeon-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/sendpigeon-sdk/health.svg)](https://phpackages.com/packages/sendpigeon-sdk)
```

###  Alternatives

[elastic-email/web-api-client

Easily send emails with Elastic Email using Web API PHP Client https://elasticemail.com/

22345.7k2](/packages/elastic-email-web-api-client)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
