Courier is a notifications API for sending messages across email, SMS, push, in-app inbox, Slack, and WhatsApp from a single API call.
require "courier"
courier = Courier::Client.new # reads COURIER_API_KEY from envresponse = courier.send_.message(
message: {
to: { user_id: "user_123" },
template: "TEMPLATE_ID",
data: { order_id: "456" },
routing: { method: "single", channels: ["email", "sms"] }
}
)
puts response.requestIdNote: the method is send_ (with trailing underscore) because send is a reserved Ruby method.
- Use
routing.method: "single"(fallback chain) unless the user explicitly asks for parallel delivery ("all"). - Use
courier.profiles.createfor partial profile updates (it merges). Usecourier.profiles.replaceonly 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 viarequest_options: { extra_headers: { "Idempotency-Key" => value } }to prevent duplicates. - Bulk sends are a 3-step flow:
courier.bulk.create_job→courier.bulk.add_users→courier.bulk.run_job. 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