import Courier from '@trycourier/courier';
const client = new Courier({
apiKey: process.env['COURIER_API_KEY'], // This is the default and can be omitted
});
const response = await client.send.message({
message: {
to: { user_id: 'user_id' },
template: 'template_id',
data: { foo: 'bar' },
},
});
console.log(response.requestId);import os
from courier import Courier
client = Courier(
api_key=os.environ.get("COURIER_API_KEY"), # This is the default and can be omitted
)
response = client.send.message(
message={
"to": {
"user_id": "user_id"
},
"template": "template_id",
"data": {
"foo": "bar"
},
},
)
print(response.request_id)package main
import (
"context"
"fmt"
"github.com/trycourier/courier-go"
"github.com/trycourier/courier-go/option"
"github.com/trycourier/courier-go/shared"
)
func main() {
client := courier.NewClient(
option.WithAPIKey("My API Key"),
)
response, err := client.Send.Message(context.TODO(), courier.SendMessageParams{
Message: courier.SendMessageParamsMessage{
To: courier.SendMessageParamsMessageToUnion{
OfUserRecipient: &shared.UserRecipientParam{
UserID: courier.String("user_id"),
},
},
Template: courier.String("template_id"),
Data: map[string]any{
"foo": "bar",
},
},
})
if err != nil {
panic(err.Error())
}
fmt.Printf("%+v\n", response.RequestID)
}
package com.courier.example;
import com.courier.client.CourierClient;
import com.courier.client.okhttp.CourierOkHttpClient;
import com.courier.models.send.SendMessageParams;
import com.courier.models.send.SendMessageResponse;
public final class Main {
private Main() {}
public static void main(String[] args) {
CourierClient client = CourierOkHttpClient.fromEnv();
SendMessageParams params = SendMessageParams.builder()
.message(SendMessageParams.Message.builder().build())
.build();
SendMessageResponse response = client.send().message(params);
}
}require "courier"
courier = Courier::Client.new(api_key: "My API Key")
response = courier.send_.message(message: {})
puts(response)<?php
require_once dirname(__DIR__) . '/vendor/autoload.php';
use Courier\Client;
use Courier\PreferenceStatus;
use Courier\ChannelClassification;
use Courier\Core\Exceptions\APIException;
$client = new Client(apiKey: getenv('COURIER_API_KEY') ?: 'My API Key');
try {
$response = $client->send->message(
message: [
'brandID' => 'brand_id',
'channels' => [
'foo' => [
'brandID' => 'brand_id',
'if' => 'if',
'metadata' => [
'utm' => [
'campaign' => 'campaign',
'content' => 'content',
'medium' => 'medium',
'source' => 'source',
'term' => 'term',
],
],
'override' => ['foo' => 'bar'],
'providers' => ['string'],
'routingMethod' => 'all',
'timeouts' => ['channel' => 0, 'provider' => 0],
],
],
'content' => ['body' => 'body', 'title' => 'title'],
'context' => ['tenantID' => 'tenant_id'],
'data' => ['foo' => 'bar'],
'delay' => [
'duration' => 0, 'timezone' => 'timezone', 'until' => 'until'
],
'expiry' => ['expiresIn' => 'string', 'expiresAt' => 'expires_at'],
'metadata' => [
'event' => 'event',
'tags' => ['string'],
'traceID' => 'trace_id',
'utm' => [
'campaign' => 'campaign',
'content' => 'content',
'medium' => 'medium',
'source' => 'source',
'term' => 'term',
],
],
'preferences' => ['subscriptionTopicID' => 'subscription_topic_id'],
'providers' => [
'foo' => [
'if' => 'if',
'metadata' => [
'utm' => [
'campaign' => 'campaign',
'content' => 'content',
'medium' => 'medium',
'source' => 'source',
'term' => 'term',
],
],
'override' => ['foo' => 'bar'],
'timeouts' => 0,
],
],
'routing' => ['channels' => ['string'], 'method' => 'all'],
'template' => 'template_id',
'timeout' => [
'channel' => ['foo' => 0],
'criteria' => 'no-escalation',
'escalation' => 0,
'message' => 0,
'provider' => ['foo' => 0],
],
'to' => [
'accountID' => 'account_id',
'context' => ['tenantID' => 'tenant_id'],
'data' => ['foo' => 'bar'],
'email' => 'email',
'listID' => 'list_id',
'locale' => 'locale',
'phoneNumber' => 'phone_number',
'preferences' => [
'notifications' => [
'foo' => [
'status' => PreferenceStatus::OPTED_IN,
'channelPreferences' => [
['channel' => ChannelClassification::DIRECT_MESSAGE]
],
'rules' => [['until' => 'until', 'start' => 'start']],
'source' => 'subscription',
],
],
'categories' => [
'foo' => [
'status' => PreferenceStatus::OPTED_IN,
'channelPreferences' => [
['channel' => ChannelClassification::DIRECT_MESSAGE]
],
'rules' => [['until' => 'until', 'start' => 'start']],
'source' => 'subscription',
],
],
'templateID' => 'templateId',
],
'tenantID' => 'tenant_id',
'userID' => 'user_id',
],
],
idempotencyKey: 'order-ORD-456-user-123',
xIdempotencyExpiration: '1785312000',
);
var_dump($response);
} catch (APIException $e) {
echo $e->getMessage();
}using System;
using System.Collections.Generic;
using System.Text.Json;
using TryCourier;
using Models = TryCourier.Models;
using TryCourier.Models.Send;
CourierClient client = new();
SendMessageParams parameters = new()
{
Message = new()
{
BrandID = "brand_id",
Channels = new Dictionary<string, Models::Channel>()
{
{ "foo", new()
{
BrandID = "brand_id",
If = "if",
Metadata = new()
{
Utm = new()
{
Campaign = "campaign",
Content = "content",
Medium = "medium",
Source = "source",
Term = "term",
},
},
Override = new Dictionary<string, JsonElement>()
{
{ "foo", JsonSerializer.SerializeToElement("bar") }
},
Providers =
[
"string"
],
RoutingMethod = Models::RoutingMethod.All,
Timeouts = new()
{
Channel = 0,
Provider = 0,
},
} },
},
Content = new Models::ElementalContentSugar()
{
Body = "body",
Title = "title",
},
Context = new() { TenantID = "tenant_id" },
Data = new Dictionary<string, JsonElement>()
{
{ "foo", JsonSerializer.SerializeToElement("bar") }
},
Delay = new()
{
Duration = 0,
Timezone = "timezone",
Until = "until",
},
Expiry = new()
{
ExpiresIn = "string",
ExpiresAt = "expires_at",
},
Metadata = new()
{
Event = "event",
Tags =
[
"string"
],
TraceID = "trace_id",
Utm = new()
{
Campaign = "campaign",
Content = "content",
Medium = "medium",
Source = "source",
Term = "term",
},
},
Preferences = new("subscription_topic_id"),
Providers = new Dictionary<string, Models::MessageProvidersType>()
{
{ "foo", new()
{
If = "if",
Metadata = new()
{
Utm = new()
{
Campaign = "campaign",
Content = "content",
Medium = "medium",
Source = "source",
Term = "term",
},
},
Override = new Dictionary<string, JsonElement>()
{
{ "foo", JsonSerializer.SerializeToElement("bar") }
},
Timeouts = 0,
} },
},
Routing = new()
{
Channels =
[
"string"
],
Method = Method.All,
},
Template = "template_id",
Timeout = new()
{
Channel = new Dictionary<string, long>() { { "foo", 0 } },
Criteria = Criteria.NoEscalation,
Escalation = 0,
Message = 0,
Provider = new Dictionary<string, long>() { { "foo", 0 } },
},
To = new Models::UserRecipient()
{
AccountID = "account_id",
Context = new() { TenantID = "tenant_id" },
Data = new Dictionary<string, JsonElement>()
{
{ "foo", JsonSerializer.SerializeToElement("bar") }
},
Email = "email",
ListID = "list_id",
Locale = "locale",
PhoneNumber = "phone_number",
Preferences = new()
{
Notifications = new Dictionary<string, Models::Preference>()
{
{ "foo", new()
{
Status = Models::PreferenceStatus.OptedIn,
ChannelPreferences =
[
new(Models::ChannelClassification.DirectMessage)
],
Rules =
[
new()
{
Until = "until",
Start = "start",
},
],
Source = Models::Source.Subscription,
} },
},
Categories = new Dictionary<string, Models::Preference>()
{
{ "foo", new()
{
Status = Models::PreferenceStatus.OptedIn,
ChannelPreferences =
[
new(Models::ChannelClassification.DirectMessage)
],
Rules =
[
new()
{
Until = "until",
Start = "start",
},
],
Source = Models::Source.Subscription,
} },
},
TemplateID = "templateId",
},
TenantID = "tenant_id",
UserID = "user_id",
},
},
};
var response = await client.Send.Message(parameters);
Console.WriteLine(response);courier send message \
--api-key 'My API Key' \
--message '{}'curl --request POST \
--url https://api.courier.com/send \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"message": {
"to": {
"user_id": "user_id"
},
"template": "template_id",
"data": {
"foo": "bar"
}
}
}
'{
"requestId": "1-67f340b1-58b7b231d9485ef0cda0a38b"
}Send a message
Sends a message to one or more recipients and returns a requestId. Courier routes it to email, SMS, push, chat, or in-app based on your rules.
import Courier from '@trycourier/courier';
const client = new Courier({
apiKey: process.env['COURIER_API_KEY'], // This is the default and can be omitted
});
const response = await client.send.message({
message: {
to: { user_id: 'user_id' },
template: 'template_id',
data: { foo: 'bar' },
},
});
console.log(response.requestId);import os
from courier import Courier
client = Courier(
api_key=os.environ.get("COURIER_API_KEY"), # This is the default and can be omitted
)
response = client.send.message(
message={
"to": {
"user_id": "user_id"
},
"template": "template_id",
"data": {
"foo": "bar"
},
},
)
print(response.request_id)package main
import (
"context"
"fmt"
"github.com/trycourier/courier-go"
"github.com/trycourier/courier-go/option"
"github.com/trycourier/courier-go/shared"
)
func main() {
client := courier.NewClient(
option.WithAPIKey("My API Key"),
)
response, err := client.Send.Message(context.TODO(), courier.SendMessageParams{
Message: courier.SendMessageParamsMessage{
To: courier.SendMessageParamsMessageToUnion{
OfUserRecipient: &shared.UserRecipientParam{
UserID: courier.String("user_id"),
},
},
Template: courier.String("template_id"),
Data: map[string]any{
"foo": "bar",
},
},
})
if err != nil {
panic(err.Error())
}
fmt.Printf("%+v\n", response.RequestID)
}
package com.courier.example;
import com.courier.client.CourierClient;
import com.courier.client.okhttp.CourierOkHttpClient;
import com.courier.models.send.SendMessageParams;
import com.courier.models.send.SendMessageResponse;
public final class Main {
private Main() {}
public static void main(String[] args) {
CourierClient client = CourierOkHttpClient.fromEnv();
SendMessageParams params = SendMessageParams.builder()
.message(SendMessageParams.Message.builder().build())
.build();
SendMessageResponse response = client.send().message(params);
}
}require "courier"
courier = Courier::Client.new(api_key: "My API Key")
response = courier.send_.message(message: {})
puts(response)<?php
require_once dirname(__DIR__) . '/vendor/autoload.php';
use Courier\Client;
use Courier\PreferenceStatus;
use Courier\ChannelClassification;
use Courier\Core\Exceptions\APIException;
$client = new Client(apiKey: getenv('COURIER_API_KEY') ?: 'My API Key');
try {
$response = $client->send->message(
message: [
'brandID' => 'brand_id',
'channels' => [
'foo' => [
'brandID' => 'brand_id',
'if' => 'if',
'metadata' => [
'utm' => [
'campaign' => 'campaign',
'content' => 'content',
'medium' => 'medium',
'source' => 'source',
'term' => 'term',
],
],
'override' => ['foo' => 'bar'],
'providers' => ['string'],
'routingMethod' => 'all',
'timeouts' => ['channel' => 0, 'provider' => 0],
],
],
'content' => ['body' => 'body', 'title' => 'title'],
'context' => ['tenantID' => 'tenant_id'],
'data' => ['foo' => 'bar'],
'delay' => [
'duration' => 0, 'timezone' => 'timezone', 'until' => 'until'
],
'expiry' => ['expiresIn' => 'string', 'expiresAt' => 'expires_at'],
'metadata' => [
'event' => 'event',
'tags' => ['string'],
'traceID' => 'trace_id',
'utm' => [
'campaign' => 'campaign',
'content' => 'content',
'medium' => 'medium',
'source' => 'source',
'term' => 'term',
],
],
'preferences' => ['subscriptionTopicID' => 'subscription_topic_id'],
'providers' => [
'foo' => [
'if' => 'if',
'metadata' => [
'utm' => [
'campaign' => 'campaign',
'content' => 'content',
'medium' => 'medium',
'source' => 'source',
'term' => 'term',
],
],
'override' => ['foo' => 'bar'],
'timeouts' => 0,
],
],
'routing' => ['channels' => ['string'], 'method' => 'all'],
'template' => 'template_id',
'timeout' => [
'channel' => ['foo' => 0],
'criteria' => 'no-escalation',
'escalation' => 0,
'message' => 0,
'provider' => ['foo' => 0],
],
'to' => [
'accountID' => 'account_id',
'context' => ['tenantID' => 'tenant_id'],
'data' => ['foo' => 'bar'],
'email' => 'email',
'listID' => 'list_id',
'locale' => 'locale',
'phoneNumber' => 'phone_number',
'preferences' => [
'notifications' => [
'foo' => [
'status' => PreferenceStatus::OPTED_IN,
'channelPreferences' => [
['channel' => ChannelClassification::DIRECT_MESSAGE]
],
'rules' => [['until' => 'until', 'start' => 'start']],
'source' => 'subscription',
],
],
'categories' => [
'foo' => [
'status' => PreferenceStatus::OPTED_IN,
'channelPreferences' => [
['channel' => ChannelClassification::DIRECT_MESSAGE]
],
'rules' => [['until' => 'until', 'start' => 'start']],
'source' => 'subscription',
],
],
'templateID' => 'templateId',
],
'tenantID' => 'tenant_id',
'userID' => 'user_id',
],
],
idempotencyKey: 'order-ORD-456-user-123',
xIdempotencyExpiration: '1785312000',
);
var_dump($response);
} catch (APIException $e) {
echo $e->getMessage();
}using System;
using System.Collections.Generic;
using System.Text.Json;
using TryCourier;
using Models = TryCourier.Models;
using TryCourier.Models.Send;
CourierClient client = new();
SendMessageParams parameters = new()
{
Message = new()
{
BrandID = "brand_id",
Channels = new Dictionary<string, Models::Channel>()
{
{ "foo", new()
{
BrandID = "brand_id",
If = "if",
Metadata = new()
{
Utm = new()
{
Campaign = "campaign",
Content = "content",
Medium = "medium",
Source = "source",
Term = "term",
},
},
Override = new Dictionary<string, JsonElement>()
{
{ "foo", JsonSerializer.SerializeToElement("bar") }
},
Providers =
[
"string"
],
RoutingMethod = Models::RoutingMethod.All,
Timeouts = new()
{
Channel = 0,
Provider = 0,
},
} },
},
Content = new Models::ElementalContentSugar()
{
Body = "body",
Title = "title",
},
Context = new() { TenantID = "tenant_id" },
Data = new Dictionary<string, JsonElement>()
{
{ "foo", JsonSerializer.SerializeToElement("bar") }
},
Delay = new()
{
Duration = 0,
Timezone = "timezone",
Until = "until",
},
Expiry = new()
{
ExpiresIn = "string",
ExpiresAt = "expires_at",
},
Metadata = new()
{
Event = "event",
Tags =
[
"string"
],
TraceID = "trace_id",
Utm = new()
{
Campaign = "campaign",
Content = "content",
Medium = "medium",
Source = "source",
Term = "term",
},
},
Preferences = new("subscription_topic_id"),
Providers = new Dictionary<string, Models::MessageProvidersType>()
{
{ "foo", new()
{
If = "if",
Metadata = new()
{
Utm = new()
{
Campaign = "campaign",
Content = "content",
Medium = "medium",
Source = "source",
Term = "term",
},
},
Override = new Dictionary<string, JsonElement>()
{
{ "foo", JsonSerializer.SerializeToElement("bar") }
},
Timeouts = 0,
} },
},
Routing = new()
{
Channels =
[
"string"
],
Method = Method.All,
},
Template = "template_id",
Timeout = new()
{
Channel = new Dictionary<string, long>() { { "foo", 0 } },
Criteria = Criteria.NoEscalation,
Escalation = 0,
Message = 0,
Provider = new Dictionary<string, long>() { { "foo", 0 } },
},
To = new Models::UserRecipient()
{
AccountID = "account_id",
Context = new() { TenantID = "tenant_id" },
Data = new Dictionary<string, JsonElement>()
{
{ "foo", JsonSerializer.SerializeToElement("bar") }
},
Email = "email",
ListID = "list_id",
Locale = "locale",
PhoneNumber = "phone_number",
Preferences = new()
{
Notifications = new Dictionary<string, Models::Preference>()
{
{ "foo", new()
{
Status = Models::PreferenceStatus.OptedIn,
ChannelPreferences =
[
new(Models::ChannelClassification.DirectMessage)
],
Rules =
[
new()
{
Until = "until",
Start = "start",
},
],
Source = Models::Source.Subscription,
} },
},
Categories = new Dictionary<string, Models::Preference>()
{
{ "foo", new()
{
Status = Models::PreferenceStatus.OptedIn,
ChannelPreferences =
[
new(Models::ChannelClassification.DirectMessage)
],
Rules =
[
new()
{
Until = "until",
Start = "start",
},
],
Source = Models::Source.Subscription,
} },
},
TemplateID = "templateId",
},
TenantID = "tenant_id",
UserID = "user_id",
},
},
};
var response = await client.Send.Message(parameters);
Console.WriteLine(response);courier send message \
--api-key 'My API Key' \
--message '{}'curl --request POST \
--url https://api.courier.com/send \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"message": {
"to": {
"user_id": "user_id"
},
"template": "template_id",
"data": {
"foo": "bar"
}
}
}
'{
"requestId": "1-67f340b1-58b7b231d9485ef0cda0a38b"
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Headers
A unique key that makes this request idempotent. If Courier receives another request with the same Idempotency-Key, it returns the stored response from the first request without performing the operation again (including the original status code and any error). Use it to safely retry POST requests after network failures without risking duplicate sends. The key is scoped to this endpoint.
How long the idempotency key remains valid, as a Unix epoch timestamp in seconds or an ISO 8601 date string. Only applies when Idempotency-Key is provided. If omitted, the key is retained for 25 hours; the maximum is 1 year.
Body
Defines the message to be delivered
Show child attributes
Show child attributes
Response
A successful call to POST /send returns a 202 status code along with a requestId in the response body.
For single-recipient requests, the requestId is the derived message_id. For multiple recipients, Courier assigns a unique message_id to each derived message.
"1-69f561d3-7ad9d453fb6a7012efc2c5ad"