Courier is a notifications API for sending messages across email, SMS, push, in-app inbox, Slack, and WhatsApp from a single API call.
<?php
use Courier\Client;
$client = new Client(apiKey: getenv('COURIER_API_KEY'));$response = $client->send->message(
message: [
'to' => ['user_id' => 'user_123'],
'template' => 'TEMPLATE_ID',
'data' => ['order_id' => '456'],
'routing' => ['method' => 'single', 'channels' => ['email', 'sms']],
],
);
var_dump($response->requestId);- Use
routing.method: "single"(fallback chain) unless the user explicitly asks for parallel delivery ("all"). - Use
$client->profiles->create()for partial profile updates (it merges). Use$client->profiles->replace()only when fully replacing all profile data. - Test and production use different API keys from the same workspace. Always confirm which environment before sending.
- For transactional sends (OTP, orders, billing), pass an
Idempotency-Keyheader viarequestOptions: ['extraHeaders' => ['Idempotency-Key' => $value]]to prevent duplicates. - Bulk sends are a 3-step flow:
$client->bulk->createJob()→$client->bulk->addUsers()→$client->bulk->runJob(). requestIdfrom a single-recipient send doubles as themessage_id. For multi-recipient sends, each recipient gets a uniquemessage_id.
template— notification template ID from the Courier dashboardrouting.method—"single"= try channels in order until one succeeds;"all"= send on every channel simultaneouslytenant_id— multi-tenant context; affects brand and preference defaults for the messagelist_id— send to all subscribers of a named listto.email/to.phone_number— ad-hoc recipient (no stored profile needed)to.user_id— registered user whose profile has channel addresses
- Full docs index: https://www.courier.com/docs/llms.txt
- API reference: https://www.courier.com/docs/reference/get-started
- MCP server: https://mcp.courier.com
- Courier Skills (Cursor / Claude Code): https://github.com/trycourier/courier-skills