import Courier from '@trycourier/courier';
const client = new Courier({
apiKey: process.env['COURIER_API_KEY'], // This is the default and can be omitted
});
const journeyResponse = await client.journeys.create({
name: 'Welcome Journey',
nodes: [
{
id: 'trigger-1',
type: 'trigger',
trigger_type: 'api-invoke',
},
{
id: 'send-1',
type: 'send',
message: { template: 'nt_01kx4h2jdafq8bk9aftxak4b40' },
},
{ id: 'exit-1', type: 'exit' },
],
enabled: true,
state: 'DRAFT',
});
console.log(journeyResponse.id);import os
from courier import Courier
client = Courier(
api_key=os.environ.get("COURIER_API_KEY"), # This is the default and can be omitted
)
journey_response = client.journeys.create(
name="Welcome Journey",
nodes=[{
"id": "trigger-1",
"type": "trigger",
"trigger_type": "api-invoke",
}, {
"id": "send-1",
"type": "send",
"message": {
"template": "nt_01kx4h2jdafq8bk9aftxak4b40"
},
}, {
"id": "exit-1",
"type": "exit",
}],
enabled=True,
state="DRAFT",
)
print(journey_response.id)package main
import (
"context"
"fmt"
"github.com/trycourier/courier-go/v4"
"github.com/trycourier/courier-go/v4/option"
)
func main() {
client := courier.NewClient(
option.WithAPIKey("My API Key"),
)
journeyResponse, err := client.Journeys.New(context.TODO(), courier.JourneyNewParams{
CreateJourneyRequest: courier.CreateJourneyRequestParam{
Name: "Welcome Journey",
Nodes: []courier.JourneyNodeUnionParam{{
OfAPIInvokeTrigger: &courier.JourneyAPIInvokeTriggerNodeParam{
TriggerType: courier.JourneyAPIInvokeTriggerNodeTriggerTypeAPIInvoke,
Type: courier.JourneyAPIInvokeTriggerNodeTypeTrigger,
},
}, {
OfSend: &courier.JourneySendNodeParam{
Message: courier.JourneySendNodeMessageParam{},
Type: courier.JourneySendNodeTypeSend,
},
}, {
OfExit: &courier.JourneyExitNodeParam{
Type: courier.JourneyExitNodeTypeExit,
},
}},
},
})
if err != nil {
panic(err.Error())
}
fmt.Printf("%+v\n", journeyResponse.ID)
}
package com.courier.example;
import com.courier.client.CourierClient;
import com.courier.client.okhttp.CourierOkHttpClient;
import com.courier.models.journeys.CreateJourneyRequest;
import com.courier.models.journeys.JourneyApiInvokeTriggerNode;
import com.courier.models.journeys.JourneyExitNode;
import com.courier.models.journeys.JourneyNode;
import com.courier.models.journeys.JourneyResponse;
import com.courier.models.journeys.JourneySendNode;
import java.util.List;
public final class Main {
private Main() {}
public static void main(String[] args) {
CourierClient client = CourierOkHttpClient.fromEnv();
CreateJourneyRequest params = CreateJourneyRequest.builder()
.name("Welcome Journey")
.nodes(List.of(
JourneyNode.ofApiInvokeTrigger(JourneyApiInvokeTriggerNode.builder()
.triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE)
.type(JourneyApiInvokeTriggerNode.Type.TRIGGER)
.build()),
JourneyNode.ofSend(JourneySendNode.builder()
.message(JourneySendNode.Message.builder().build())
.type(JourneySendNode.Type.SEND)
.build()),
JourneyNode.ofExit(JourneyExitNode.builder()
.type(JourneyExitNode.Type.EXIT)
.build())
))
.build();
JourneyResponse journeyResponse = client.journeys().create(params);
}
}require "courier"
courier = Courier::Client.new(api_key: "My API Key")
journey_response = courier.journeys.create(
name: "Welcome Journey",
nodes: [{trigger_type: :"api-invoke", type: :trigger}, {message: {}, type: :send}, {type: :exit}]
)
puts(journey_response)<?php
require_once dirname(__DIR__) . '/vendor/autoload.php';
use Courier\Client;
use Courier\Core\Exceptions\APIException;
use Courier\Journeys\JourneyState;
$client = new Client(apiKey: getenv('COURIER_API_KEY') ?: 'My API Key');
try {
$journeyResponse = $client->journeys->create(
name: 'Welcome Journey',
nodes: [
[
'triggerType' => 'api-invoke',
'type' => 'trigger',
'id' => 'trigger-1',
'conditions' => ['string', 'string'],
'schema' => ['foo' => 'bar'],
],
[
'message' => [
'context' => ['tenantID' => 'x'],
'data' => ['foo' => 'bar'],
'delay' => ['until' => 'x', 'timezone' => 'x'],
'template' => 'nt_01kx4h2jdafq8bk9aftxak4b40',
'to' => [
'emailOverride' => 'x',
'phoneNumberOverride' => 'x',
'userIDOverride' => 'x',
],
],
'type' => 'send',
'id' => 'send-1',
'conditions' => ['string', 'string'],
'experiment' => [
'bucketingKey' => 'x',
'variants' => [
['id' => 'x', 'templateID' => 'x', 'weight' => 0, 'name' => 'name'],
['id' => 'x', 'templateID' => 'x', 'weight' => 0, 'name' => 'name'],
],
'id' => 'x',
'name' => 'name',
],
],
['type' => 'exit', 'id' => 'exit-1'],
],
enabled: true,
state: JourneyState::DRAFT,
idempotencyKey: 'order-ORD-456-user-123',
xIdempotencyExpiration: '1785312000',
);
var_dump($journeyResponse);
} catch (APIException $e) {
echo $e->getMessage();
}using System;
using System.Collections.Generic;
using System.Text.Json;
using TryCourier;
using TryCourier.Models.Journeys;
CourierClient client = new();
JourneyCreateParams parameters = new()
{
Name = "Welcome Journey",
Nodes =
[
new JourneyApiInvokeTriggerNode()
{
TriggerType = TriggerType.ApiInvoke,
Type = JourneyApiInvokeTriggerNodeType.Trigger,
ID = "trigger-1",
Conditions = new(
[
"string", "string"
]
),
Schema = new Dictionary<string, JsonElement>()
{
{ "foo", JsonSerializer.SerializeToElement("bar") }
},
},
new JourneySendNode()
{
Message = new()
{
Context = new("x"),
Data = new Dictionary<string, JsonElement>()
{
{ "foo", JsonSerializer.SerializeToElement("bar") }
},
Delay = new()
{
Until = "x",
Timezone = "x",
},
Template = "nt_01kx4h2jdafq8bk9aftxak4b40",
To = new()
{
EmailOverride = "x",
PhoneNumberOverride = "x",
UserIDOverride = "x",
},
},
Type = JourneySendNodeType.Send,
ID = "send-1",
Conditions = new(
[
"string", "string"
]
),
Experiment = new()
{
BucketingKey = "x",
Variants =
[
new()
{
ID = "x",
TemplateID = "x",
Weight = 0,
Name = "name",
},
new()
{
ID = "x",
TemplateID = "x",
Weight = 0,
Name = "name",
},
],
ID = "x",
Name = "name",
},
},
new JourneyExitNode()
{
Type = JourneyExitNodeType.Exit,
ID = "exit-1",
},
],
};
var journeyResponse = await client.Journeys.Create(parameters);
Console.WriteLine(journeyResponse);courier journeys create \
--api-key 'My API Key' \
--name 'Welcome Journey' \
--node '{trigger_type: api-invoke, type: trigger}' \
--node '{message: {}, type: send}' \
--node '{type: exit}'curl --request POST \
--url https://api.courier.com/journeys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Welcome Journey",
"state": "DRAFT",
"enabled": true,
"nodes": [
{
"id": "trigger-1",
"type": "trigger",
"trigger_type": "api-invoke"
},
{
"id": "send-1",
"type": "send",
"message": {
"template": "nt_01kx4h2jdafq8bk9aftxak4b40"
}
},
{
"id": "exit-1",
"type": "exit"
}
]
}
'{
"id": "jry_01kx4m9ntrfk6vnxzww2rbpfd1",
"name": "Welcome Journey",
"state": "DRAFT",
"enabled": true,
"nodes": [],
"created": 1715000000000,
"creator": "user-1",
"updated": 1715000000000,
"updater": "user-1",
"published": null
}{
"message": "Example message text",
"type": "invalid_request_error"
}{
"message": "Example message text",
"type": "invalid_request_error"
}{
"message": "Example message text",
"type": "invalid_request_error"
}Create a journey
Creates a journey from a set of nodes, in draft state unless you pass a published state. Send nodes cannot be included until their templates exist.
import Courier from '@trycourier/courier';
const client = new Courier({
apiKey: process.env['COURIER_API_KEY'], // This is the default and can be omitted
});
const journeyResponse = await client.journeys.create({
name: 'Welcome Journey',
nodes: [
{
id: 'trigger-1',
type: 'trigger',
trigger_type: 'api-invoke',
},
{
id: 'send-1',
type: 'send',
message: { template: 'nt_01kx4h2jdafq8bk9aftxak4b40' },
},
{ id: 'exit-1', type: 'exit' },
],
enabled: true,
state: 'DRAFT',
});
console.log(journeyResponse.id);import os
from courier import Courier
client = Courier(
api_key=os.environ.get("COURIER_API_KEY"), # This is the default and can be omitted
)
journey_response = client.journeys.create(
name="Welcome Journey",
nodes=[{
"id": "trigger-1",
"type": "trigger",
"trigger_type": "api-invoke",
}, {
"id": "send-1",
"type": "send",
"message": {
"template": "nt_01kx4h2jdafq8bk9aftxak4b40"
},
}, {
"id": "exit-1",
"type": "exit",
}],
enabled=True,
state="DRAFT",
)
print(journey_response.id)package main
import (
"context"
"fmt"
"github.com/trycourier/courier-go/v4"
"github.com/trycourier/courier-go/v4/option"
)
func main() {
client := courier.NewClient(
option.WithAPIKey("My API Key"),
)
journeyResponse, err := client.Journeys.New(context.TODO(), courier.JourneyNewParams{
CreateJourneyRequest: courier.CreateJourneyRequestParam{
Name: "Welcome Journey",
Nodes: []courier.JourneyNodeUnionParam{{
OfAPIInvokeTrigger: &courier.JourneyAPIInvokeTriggerNodeParam{
TriggerType: courier.JourneyAPIInvokeTriggerNodeTriggerTypeAPIInvoke,
Type: courier.JourneyAPIInvokeTriggerNodeTypeTrigger,
},
}, {
OfSend: &courier.JourneySendNodeParam{
Message: courier.JourneySendNodeMessageParam{},
Type: courier.JourneySendNodeTypeSend,
},
}, {
OfExit: &courier.JourneyExitNodeParam{
Type: courier.JourneyExitNodeTypeExit,
},
}},
},
})
if err != nil {
panic(err.Error())
}
fmt.Printf("%+v\n", journeyResponse.ID)
}
package com.courier.example;
import com.courier.client.CourierClient;
import com.courier.client.okhttp.CourierOkHttpClient;
import com.courier.models.journeys.CreateJourneyRequest;
import com.courier.models.journeys.JourneyApiInvokeTriggerNode;
import com.courier.models.journeys.JourneyExitNode;
import com.courier.models.journeys.JourneyNode;
import com.courier.models.journeys.JourneyResponse;
import com.courier.models.journeys.JourneySendNode;
import java.util.List;
public final class Main {
private Main() {}
public static void main(String[] args) {
CourierClient client = CourierOkHttpClient.fromEnv();
CreateJourneyRequest params = CreateJourneyRequest.builder()
.name("Welcome Journey")
.nodes(List.of(
JourneyNode.ofApiInvokeTrigger(JourneyApiInvokeTriggerNode.builder()
.triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE)
.type(JourneyApiInvokeTriggerNode.Type.TRIGGER)
.build()),
JourneyNode.ofSend(JourneySendNode.builder()
.message(JourneySendNode.Message.builder().build())
.type(JourneySendNode.Type.SEND)
.build()),
JourneyNode.ofExit(JourneyExitNode.builder()
.type(JourneyExitNode.Type.EXIT)
.build())
))
.build();
JourneyResponse journeyResponse = client.journeys().create(params);
}
}require "courier"
courier = Courier::Client.new(api_key: "My API Key")
journey_response = courier.journeys.create(
name: "Welcome Journey",
nodes: [{trigger_type: :"api-invoke", type: :trigger}, {message: {}, type: :send}, {type: :exit}]
)
puts(journey_response)<?php
require_once dirname(__DIR__) . '/vendor/autoload.php';
use Courier\Client;
use Courier\Core\Exceptions\APIException;
use Courier\Journeys\JourneyState;
$client = new Client(apiKey: getenv('COURIER_API_KEY') ?: 'My API Key');
try {
$journeyResponse = $client->journeys->create(
name: 'Welcome Journey',
nodes: [
[
'triggerType' => 'api-invoke',
'type' => 'trigger',
'id' => 'trigger-1',
'conditions' => ['string', 'string'],
'schema' => ['foo' => 'bar'],
],
[
'message' => [
'context' => ['tenantID' => 'x'],
'data' => ['foo' => 'bar'],
'delay' => ['until' => 'x', 'timezone' => 'x'],
'template' => 'nt_01kx4h2jdafq8bk9aftxak4b40',
'to' => [
'emailOverride' => 'x',
'phoneNumberOverride' => 'x',
'userIDOverride' => 'x',
],
],
'type' => 'send',
'id' => 'send-1',
'conditions' => ['string', 'string'],
'experiment' => [
'bucketingKey' => 'x',
'variants' => [
['id' => 'x', 'templateID' => 'x', 'weight' => 0, 'name' => 'name'],
['id' => 'x', 'templateID' => 'x', 'weight' => 0, 'name' => 'name'],
],
'id' => 'x',
'name' => 'name',
],
],
['type' => 'exit', 'id' => 'exit-1'],
],
enabled: true,
state: JourneyState::DRAFT,
idempotencyKey: 'order-ORD-456-user-123',
xIdempotencyExpiration: '1785312000',
);
var_dump($journeyResponse);
} catch (APIException $e) {
echo $e->getMessage();
}using System;
using System.Collections.Generic;
using System.Text.Json;
using TryCourier;
using TryCourier.Models.Journeys;
CourierClient client = new();
JourneyCreateParams parameters = new()
{
Name = "Welcome Journey",
Nodes =
[
new JourneyApiInvokeTriggerNode()
{
TriggerType = TriggerType.ApiInvoke,
Type = JourneyApiInvokeTriggerNodeType.Trigger,
ID = "trigger-1",
Conditions = new(
[
"string", "string"
]
),
Schema = new Dictionary<string, JsonElement>()
{
{ "foo", JsonSerializer.SerializeToElement("bar") }
},
},
new JourneySendNode()
{
Message = new()
{
Context = new("x"),
Data = new Dictionary<string, JsonElement>()
{
{ "foo", JsonSerializer.SerializeToElement("bar") }
},
Delay = new()
{
Until = "x",
Timezone = "x",
},
Template = "nt_01kx4h2jdafq8bk9aftxak4b40",
To = new()
{
EmailOverride = "x",
PhoneNumberOverride = "x",
UserIDOverride = "x",
},
},
Type = JourneySendNodeType.Send,
ID = "send-1",
Conditions = new(
[
"string", "string"
]
),
Experiment = new()
{
BucketingKey = "x",
Variants =
[
new()
{
ID = "x",
TemplateID = "x",
Weight = 0,
Name = "name",
},
new()
{
ID = "x",
TemplateID = "x",
Weight = 0,
Name = "name",
},
],
ID = "x",
Name = "name",
},
},
new JourneyExitNode()
{
Type = JourneyExitNodeType.Exit,
ID = "exit-1",
},
],
};
var journeyResponse = await client.Journeys.Create(parameters);
Console.WriteLine(journeyResponse);courier journeys create \
--api-key 'My API Key' \
--name 'Welcome Journey' \
--node '{trigger_type: api-invoke, type: trigger}' \
--node '{message: {}, type: send}' \
--node '{type: exit}'curl --request POST \
--url https://api.courier.com/journeys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Welcome Journey",
"state": "DRAFT",
"enabled": true,
"nodes": [
{
"id": "trigger-1",
"type": "trigger",
"trigger_type": "api-invoke"
},
{
"id": "send-1",
"type": "send",
"message": {
"template": "nt_01kx4h2jdafq8bk9aftxak4b40"
}
},
{
"id": "exit-1",
"type": "exit"
}
]
}
'{
"id": "jry_01kx4m9ntrfk6vnxzww2rbpfd1",
"name": "Welcome Journey",
"state": "DRAFT",
"enabled": true,
"nodes": [],
"created": 1715000000000,
"creator": "user-1",
"updated": 1715000000000,
"updater": "user-1",
"published": null
}{
"message": "Example message text",
"type": "invalid_request_error"
}{
"message": "Example message text",
"type": "invalid_request_error"
}{
"message": "Example message text",
"type": "invalid_request_error"
}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
Request body for creating a journey.
11A single node in a journey DAG. Discriminated by type, with a secondary discriminator on some variants (trigger_type for trigger, mode for delay, method for fetch, scope for throttle).
- API Invoke Trigger
- Segment Trigger
- Send
- Delay for Duration
- Delay Until
- Fetch (GET/DELETE)
- Fetch (POST/PUT)
- AI
- Throttle (Static)
- Throttle (Dynamic)
- Batch
- Add to Digest
- Exit
- JourneyBranchNode
Show child attributes
Show child attributes
Lifecycle state of a journey.
DRAFT, PUBLISHED Response
Journey created
A journey, with its current draft or published nodes and metadata.
Lifecycle state of a journey.
DRAFT, PUBLISHED A single node in a journey DAG. Discriminated by type, with a secondary discriminator on some variants (trigger_type for trigger, mode for delay, method for fetch, scope for throttle).
- API Invoke Trigger
- Segment Trigger
- Send
- Delay for Duration
- Delay Until
- Fetch (GET/DELETE)
- Fetch (POST/PUT)
- AI
- Throttle (Static)
- Throttle (Dynamic)
- Batch
- Add to Digest
- Exit
- JourneyBranchNode
Show child attributes
Show child attributes