How to Send iMessages from PHP (Laravel & WordPress)
PHP developers can send iMessages using the Sendblue REST API with plain cURL, Laravel's HTTP client, or WordPress's wp_remote_post. This guide covers all three approaches with complete code examples for sending messages, receiving webhooks, and handling media.
Prerequisites
You need:
- PHP 8.0+ with the cURL extension enabled (standard on most installs)
- Sendblue API credentials — sign up free to get your API key and secret
- For Laravel: Laravel 10+ with the HTTP client (included by default)
- For WordPress: WordPress 5.0+
The Sendblue API uses standard JSON over HTTPS, so no special PHP extensions are needed beyond cURL.
Plain PHP with cURL
Here's how to send an iMessage using PHP's built-in cURL functions:
<?php
function sendImessage(string $number, string $content, ?string $mediaUrl = null): array
{
$payload = [
'number' => $number,
'content' => $content,
];
if ($mediaUrl) {
$payload['media_url'] = $mediaUrl;
}
$ch = curl_init('https://api.sendblue.co/api/send-message');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'sb-api-key-id: ' . $_ENV['SENDBLUE_API_KEY'],
'sb-api-secret-key: ' . $_ENV['SENDBLUE_API_SECRET'],
],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return json_decode($response, true);
}
// Send a message
$result = sendImessage('+15551234567', 'Hello from PHP!');
print_r($result);This works on any PHP installation with cURL enabled — shared hosting, VPS, Docker, or serverless.
Laravel Integration
Laravel's HTTP client makes API calls much cleaner. Create a service class:
<?php
// app/Services/SendblueService.php
namespace App\Services;
use Illuminate\Support\Facades\Http;
class SendblueService
{
private string $baseUrl = 'https://api.sendblue.co';
public function sendMessage(
string $number,
string $content,
?string $sendStyle = null,
?string $mediaUrl = null
): array {
$payload = compact('number', 'content');
if ($sendStyle) $payload['send_style'] = $sendStyle;
if ($mediaUrl) $payload['media_url'] = $mediaUrl;
$response = Http::withHeaders([
'sb-api-key-id' => config('services.sendblue.key'),
'sb-api-secret-key' => config('services.sendblue.secret'),
])->post("{$this->baseUrl}/api/send-message", $payload);
return $response->json();
}
public function evaluateService(string $number): array
{
$response = Http::withHeaders([
'sb-api-key-id' => config('services.sendblue.key'),
'sb-api-secret-key' => config('services.sendblue.secret'),
])->get("{$this->baseUrl}/api/evaluate-service", [
'number' => $number,
]);
return $response->json();
}
}Add your credentials to config/services.php:
// config/services.php
'sendblue' => [
'key' => env('SENDBLUE_API_KEY'),
'secret' => env('SENDBLUE_API_SECRET'),
],Now use it anywhere in your Laravel app:
// In a controller or command:
$sendblue = new SendblueService();
$sendblue->sendMessage(
number: '+15551234567',
content: 'Your appointment is confirmed for tomorrow at 2pm.',
sendStyle: 'celebration'
);WordPress Integration
WordPress has its own HTTP helper that works without any additional plugins:
<?php
function sb_send_imessage($number, $content, $media_url = null) {
$body = [
'number' => $number,
'content' => $content,
];
if ($media_url) {
$body['media_url'] = $media_url;
}
$response = wp_remote_post('https://api.sendblue.co/api/send-message', [
'headers' => [
'Content-Type' => 'application/json',
'sb-api-key-id' => get_option('sendblue_api_key'),
'sb-api-secret-key' => get_option('sendblue_api_secret'),
],
'body' => wp_json_encode($body),
]);
if (is_wp_error($response)) {
error_log('Sendblue error: ' . $response->get_error_message());
return null;
}
return json_decode(wp_remote_retrieve_body($response), true);
}
// Example: Send message when a WooCommerce order is placed
add_action('woocommerce_order_status_completed', function($order_id) {
$order = wc_get_order($order_id);
$phone = $order->get_billing_phone();
sb_send_imessage(
$phone,
"Your order #{$order_id} has shipped! Track it here: https://example.com/track/{$order_id}"
);
});Store your API credentials in WordPress options or wp-config.php constants for security.
Receive Webhooks in Laravel
Set up a webhook route and controller to handle incoming messages:
<?php
// routes/api.php
Route::post('/webhooks/sendblue/receive', [WebhookController::class, 'receive']);
// app/Http/Controllers/WebhookController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Services\SendblueService;
class WebhookController extends Controller
{
public function receive(Request $request)
{
$fromNumber = $request->input('from_number');
$content = $request->input('content');
$mediaUrl = $request->input('media_url');
$service = $request->input('service'); // iMessage, SMS, or RCS
\Log::info("Received {$service} from {$fromNumber}: {$content}");
// Save to database
\App\Models\Message::create([
'from_number' => $fromNumber,
'content' => $content,
'media_url' => $mediaUrl,
'service' => $service,
]);
// Auto-reply
(new SendblueService())->sendMessage(
number: $fromNumber,
content: 'Thanks for your message! Our team will reply shortly.'
);
return response()->json(['status' => 'ok']);
}
}Make sure to exclude this route from CSRF protection in app/Http/Middleware/VerifyCsrfToken.php. Set your webhook URL in the Sendblue dashboard.
Send Media and Contact Cards
Attach images, PDFs, videos, or vCards to any message:
// Send an image
$sendblue->sendMessage(
number: '+15551234567',
content: 'Here is your receipt:',
mediaUrl: 'https://example.com/receipt.pdf'
);
// Send a contact card (vCard)
$sendblue->sendMessage(
number: '+15551234567',
mediaUrl: 'https://example.com/agent.vcf'
);Contact cards are a powerful feature unique to Sendblue. When a recipient saves the vCard, your business name appears on all future messages. This is especially effective for sales outreach and customer support.
Error Handling
Always handle API errors gracefully. Here's a robust pattern for Laravel:
public function sendMessage(string $number, string $content): array
{
try {
$response = Http::withHeaders([
'sb-api-key-id' => config('services.sendblue.key'),
'sb-api-secret-key' => config('services.sendblue.secret'),
])
->timeout(30)
->retry(3, 1000)
->post('https://api.sendblue.co/api/send-message', [
'number' => $number,
'content' => $content,
]);
if ($response->failed()) {
\Log::error('Sendblue API error', [
'status' => $response->status(),
'body' => $response->json(),
]);
}
return $response->json();
} catch (\Exception $e) {
\Log::error('Sendblue exception: ' . $e->getMessage());
return ['error' => $e->getMessage()];
}
}Laravel's HTTP client supports built-in retries and timeouts, which is ideal for reliable message delivery.
Next Steps
You're now sending iMessages from PHP. Explore further:
- Full API documentation — Group messaging, typing indicators, reactions, and more
- Webhook integration guide — Handle all 7 webhook types
- CRM integrations — Connect iMessage to HubSpot, Salesforce, and other tools
- Build an AI agent — Connect Claude or GPT to iMessage
Get your free API keys and start sending iMessages from PHP today.
Ready to send your first iMessage?
Get API access in minutes. Free sandbox, no credit card required.