> ## Documentation Index
> Fetch the complete documentation index at: https://www.courier.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a journey

> Create a journey. Defaults to `DRAFT` state; pass `state: "PUBLISHED"` to publish on create. Send nodes are not allowed on `POST`. The standard flow is: create the journey shell here, add notification templates with `POST /journeys/{templateId}/templates`, then wire them into the journey with `PUT /journeys/{templateId}`. Call `POST /journeys/{templateId}/publish` to publish a draft after the fact.



## OpenAPI

````yaml /openapi-specs/openapi.documented.yml post /journeys
openapi: 3.0.1
info:
  title: Courier
  description: The Courier REST API.
  version: 0.0.1
servers:
  - url: https://api.courier.com
    description: Production
security: []
paths:
  /journeys:
    post:
      tags:
        - Journeys
      summary: Create a journey
      description: >-
        Create a journey. Defaults to `DRAFT` state; pass `state: "PUBLISHED"`
        to publish on create. Send nodes are not allowed on `POST`. The standard
        flow is: create the journey shell here, add notification templates with
        `POST /journeys/{templateId}/templates`, then wire them into the journey
        with `PUT /journeys/{templateId}`. Call `POST
        /journeys/{templateId}/publish` to publish a draft after the fact.
      operationId: journeys_create
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateJourneyRequest'
            examples:
              Example1:
                summary: Welcome journey with a trigger and a send
                value:
                  name: Welcome Journey
                  state: DRAFT
                  enabled: true
                  nodes:
                    - id: trigger-1
                      type: trigger
                      trigger_type: api
                    - id: send-1
                      type: send
      responses:
        '201':
          description: Journey created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JourneyResponse'
              examples:
                Example1:
                  summary: Created journey
                  value:
                    id: abc-123
                    name: Welcome Journey
                    state: DRAFT
                    enabled: true
                    nodes: []
                    created: 1715000000000
                    creator: user-1
                    updated: 1715000000000
                    updater: user-1
                    published: null
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BadRequest'
        '404':
          description: Not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotFound'
        '422':
          description: Unprocessable entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnprocessableEntity'
      security:
        - BearerAuth: []
      x-codeSamples:
        - lang: JavaScript
          source: |-
            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',
                },
                { id: 'send-1', type: 'send' },
              ],
              enabled: true,
              state: 'DRAFT',
            });

            console.log(journeyResponse.id);
        - lang: Python
          source: |-
            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",
                }, {
                    "id": "send-1",
                    "type": "send",
                }],
                enabled=True,
                state="DRAFT",
            )
            print(journey_response.id)
        - lang: Go
          source: "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/trycourier/courier-go\"\n\t\"github.com/trycourier/courier-go/option\"\n)\n\nfunc main() {\n\tclient := courier.NewClient(\n\t\toption.WithAPIKey(\"My API Key\"),\n\t)\n\tjourneyResponse, err := client.Journeys.New(context.TODO(), courier.JourneyNewParams{\n\t\tCreateJourneyRequest: courier.CreateJourneyRequestParam{\n\t\t\tName: \"Welcome Journey\",\n\t\t\tNodes: []courier.JourneyNodeUnionParam{{\n\t\t\t\tOfAPIInvokeTrigger: &courier.JourneyAPIInvokeTriggerNodeParam{\n\t\t\t\t\tTriggerType: courier.JourneyAPIInvokeTriggerNodeTriggerTypeAPIInvoke,\n\t\t\t\t\tType:        courier.JourneyAPIInvokeTriggerNodeTypeTrigger,\n\t\t\t\t},\n\t\t\t}, {\n\t\t\t\tOfAPIInvokeTrigger: &courier.JourneyAPIInvokeTriggerNodeParam{\n\t\t\t\t\tTriggerType: courier.JourneyAPIInvokeTriggerNodeTriggerTypeAPIInvoke,\n\t\t\t\t\tType:        courier.JourneyAPIInvokeTriggerNodeTypeTrigger,\n\t\t\t\t},\n\t\t\t}},\n\t\t},\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf(\"%+v\\n\", journeyResponse.ID)\n}\n"
        - lang: Java
          source: |-
            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.JourneyResponse;

            public final class Main {
                private Main() {}

                public static void main(String[] args) {
                    CourierClient client = CourierOkHttpClient.fromEnv();

                    CreateJourneyRequest params = CreateJourneyRequest.builder()
                        .name("Welcome Journey")
                        .addNode(JourneyApiInvokeTriggerNode.builder()
                            .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE)
                            .type(JourneyApiInvokeTriggerNode.Type.TRIGGER)
                            .build())
                        .addNode(JourneyApiInvokeTriggerNode.builder()
                            .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE)
                            .type(JourneyApiInvokeTriggerNode.Type.TRIGGER)
                            .build())
                        .build();
                    JourneyResponse journeyResponse = client.journeys().create(params);
                }
            }
        - lang: Ruby
          source: |-
            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}, {trigger_type: :"api-invoke", type: :trigger}]
            )

            puts(journey_response)
        - lang: PHP
          source: >-
            <?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'],
                  ],
                  [
                    'triggerType' => 'api-invoke',
                    'type' => 'trigger',
                    'id' => 'send-1',
                    'conditions' => ['string', 'string'],
                    'schema' => ['foo' => 'bar'],
                  ],
                ],
                enabled: true,
                state: JourneyState::DRAFT,
              );

              var_dump($journeyResponse);
            } catch (APIException $e) {
              echo $e->getMessage();
            }
        - lang: C#
          source: |-
            using System;
            using System.Collections.Generic;
            using System.Text.Json;
            using Courier;
            using Courier.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 JourneyApiInvokeTriggerNode()
                    {
                        TriggerType = TriggerType.ApiInvoke,
                        Type = JourneyApiInvokeTriggerNodeType.Trigger,
                        ID = "send-1",
                        Conditions = new(

                            [
                                "string", "string"
                            ]
                        ),
                        Schema = new Dictionary<string, JsonElement>()
                        {
                            { "foo", JsonSerializer.SerializeToElement("bar") }
                        },
                    },
                ],
            };

            var journeyResponse = await client.Journeys.Create(parameters);

            Console.WriteLine(journeyResponse);
        - lang: CLI
          source: |-
            courier journeys create \
              --api-key 'My API Key' \
              --name 'Welcome Journey' \
              --node '{trigger_type: api-invoke, type: trigger}' \
              --node '{trigger_type: api-invoke, type: trigger}'
components:
  schemas:
    CreateJourneyRequest:
      description: Request body for creating a journey.
      type: object
      properties:
        name:
          type: string
          minLength: 1
        nodes:
          minItems: 1
          type: array
          items:
            $ref: '#/components/schemas/JourneyNode'
        enabled:
          type: boolean
        state:
          allOf:
            - $ref: '#/components/schemas/JourneyState'
      required:
        - name
        - nodes
    JourneyResponse:
      description: A journey, with its current draft or published nodes and metadata.
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        state:
          $ref: '#/components/schemas/JourneyState'
        enabled:
          type: boolean
        nodes:
          type: array
          items:
            $ref: '#/components/schemas/JourneyNode'
        created:
          nullable: true
          type: integer
          format: int64
        creator:
          type: string
          nullable: true
        updated:
          nullable: true
          type: integer
          format: int64
        updater:
          type: string
          nullable: true
        published:
          nullable: true
          type: integer
          format: int64
      required:
        - id
        - name
        - state
        - enabled
        - nodes
        - created
        - creator
        - updated
        - updater
        - published
    BadRequest:
      title: BadRequest
      type: object
      properties:
        type:
          type: string
          enum:
            - invalid_request_error
      required:
        - type
      allOf:
        - $ref: '#/components/schemas/BaseError'
    NotFound:
      title: NotFound
      type: object
      properties:
        type:
          type: string
          enum:
            - invalid_request_error
      required:
        - type
      allOf:
        - $ref: '#/components/schemas/BaseError'
    UnprocessableEntity:
      title: UnprocessableEntity
      type: object
      properties:
        type:
          type: string
          enum:
            - invalid_request_error
      required:
        - type
      allOf:
        - $ref: '#/components/schemas/BaseError'
    JourneyNode:
      description: >-
        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).
      oneOf:
        - $ref: '#/components/schemas/JourneyApiInvokeTriggerNode'
        - $ref: '#/components/schemas/JourneySegmentTriggerNode'
        - $ref: '#/components/schemas/JourneySendNode'
        - $ref: '#/components/schemas/JourneyDelayDurationNode'
        - $ref: '#/components/schemas/JourneyDelayUntilNode'
        - $ref: '#/components/schemas/JourneyFetchGetDeleteNode'
        - $ref: '#/components/schemas/JourneyFetchPostPutNode'
        - $ref: '#/components/schemas/JourneyAINode'
        - $ref: '#/components/schemas/JourneyThrottleStaticNode'
        - $ref: '#/components/schemas/JourneyThrottleDynamicNode'
        - $ref: '#/components/schemas/JourneyBatchNode'
        - $ref: '#/components/schemas/JourneyExitNode'
        - type: object
          title: JourneyBranchNode
          description: >-
            Branch node. Routes to the first entry in `paths[]` whose
            `conditions` match, else falls through to `default.nodes`.
          properties:
            id:
              type: string
              minLength: 1
            type:
              type: string
              enum:
                - branch
            paths:
              type: array
              minItems: 1
              items:
                type: object
                properties:
                  label:
                    type: string
                    minLength: 1
                  conditions:
                    $ref: '#/components/schemas/JourneyConditionsField'
                  nodes:
                    type: array
                    items:
                      $ref: '#/components/schemas/JourneyNode'
                required:
                  - conditions
                  - nodes
            default:
              type: object
              properties:
                label:
                  type: string
                  minLength: 1
                nodes:
                  type: array
                  items:
                    $ref: '#/components/schemas/JourneyNode'
              required:
                - nodes
          required:
            - type
            - paths
            - default
    JourneyState:
      description: Lifecycle state of a journey.
      type: string
      enum:
        - DRAFT
        - PUBLISHED
    BaseError:
      title: BaseError
      type: object
      properties:
        message:
          type: string
          description: A message describing the error that occurred.
      required:
        - message
    JourneyApiInvokeTriggerNode:
      title: API Invoke Trigger
      description: >-
        Trigger fired when the journey is invoked via the API. The optional
        `schema` field is a JSON Schema that validates the invocation payload.
      type: object
      properties:
        id:
          type: string
          minLength: 1
        type:
          type: string
          enum:
            - trigger
        trigger_type:
          type: string
          enum:
            - api-invoke
        schema:
          type: object
          additionalProperties: true
          description: >-
            A JSONSchema object (Draft-07-compatible). Validated at runtime by
            Ajv.
        conditions:
          $ref: '#/components/schemas/JourneyConditionsField'
      required:
        - type
        - trigger_type
    JourneySegmentTriggerNode:
      title: Segment Trigger
      description: Trigger fired by a segment event (`identify`, `group`, or `track`).
      type: object
      properties:
        id:
          type: string
          minLength: 1
        type:
          type: string
          enum:
            - trigger
        trigger_type:
          type: string
          enum:
            - segment
        request_type:
          type: string
          enum:
            - identify
            - group
            - track
        event_id:
          type: string
          minLength: 1
        conditions:
          $ref: '#/components/schemas/JourneyConditionsField'
      required:
        - type
        - trigger_type
        - request_type
    JourneySendNode:
      title: Send
      description: >-
        Send a notification template to the recipient. Optionally override the
        recipient address, delay the send, or attach `data`.
      type: object
      properties:
        id:
          type: string
          minLength: 1
        type:
          type: string
          enum:
            - send
        message:
          type: object
          properties:
            template:
              type: string
              minLength: 1
            to:
              type: object
              properties:
                email_override:
                  type: string
                  minLength: 1
                phone_number_override:
                  type: string
                  minLength: 1
                user_id_override:
                  type: string
                  minLength: 1
            delay:
              type: object
              properties:
                until:
                  type: string
                  minLength: 1
                timezone:
                  type: string
                  minLength: 1
              required:
                - until
            data:
              type: object
              additionalProperties: true
          required:
            - template
        conditions:
          $ref: '#/components/schemas/JourneyConditionsField'
      required:
        - type
        - message
    JourneyDelayDurationNode:
      title: Delay for Duration
      description: Pause the journey run for a fixed `duration`.
      type: object
      properties:
        id:
          type: string
          minLength: 1
        type:
          type: string
          enum:
            - delay
        mode:
          type: string
          enum:
            - duration
        duration:
          type: string
          minLength: 1
        conditions:
          $ref: '#/components/schemas/JourneyConditionsField'
      required:
        - type
        - mode
        - duration
    JourneyDelayUntilNode:
      title: Delay Until
      description: Pause the journey run `until` a specific time.
      type: object
      properties:
        id:
          type: string
          minLength: 1
        type:
          type: string
          enum:
            - delay
        mode:
          type: string
          enum:
            - until
        until:
          type: string
          minLength: 1
        conditions:
          $ref: '#/components/schemas/JourneyConditionsField'
      required:
        - type
        - mode
        - until
    JourneyFetchGetDeleteNode:
      title: Fetch (GET/DELETE)
      description: >-
        Issue an HTTP GET or DELETE request and merge the response into the
        journey state per `merge_strategy`.
      type: object
      properties:
        id:
          type: string
          minLength: 1
        type:
          type: string
          enum:
            - fetch
        method:
          type: string
          enum:
            - get
            - delete
        url:
          type: string
          minLength: 1
        merge_strategy:
          $ref: '#/components/schemas/JourneyMergeStrategy'
        headers:
          type: object
          additionalProperties:
            type: string
        query_params:
          type: object
          additionalProperties:
            type: string
        response_schema:
          type: object
          additionalProperties: true
          description: >-
            A JSONSchema object (Draft-07-compatible). Validated at runtime by
            Ajv.
        conditions:
          $ref: '#/components/schemas/JourneyConditionsField'
      required:
        - type
        - method
        - url
        - merge_strategy
    JourneyFetchPostPutNode:
      title: Fetch (POST/PUT)
      description: >-
        Issue an HTTP POST or PUT request with a `body` and merge the response
        into the journey state per `merge_strategy`.
      type: object
      properties:
        id:
          type: string
          minLength: 1
        type:
          type: string
          enum:
            - fetch
        method:
          type: string
          enum:
            - post
            - put
        url:
          type: string
          minLength: 1
        merge_strategy:
          $ref: '#/components/schemas/JourneyMergeStrategy'
        headers:
          type: object
          additionalProperties:
            type: string
        query_params:
          type: object
          additionalProperties:
            type: string
        response_schema:
          type: object
          additionalProperties: true
          description: >-
            A JSONSchema object (Draft-07-compatible). Validated at runtime by
            Ajv.
        body:
          type: string
        conditions:
          $ref: '#/components/schemas/JourneyConditionsField'
      required:
        - type
        - method
        - url
        - merge_strategy
    JourneyAINode:
      title: AI
      description: >-
        Invoke an AI step with `user_prompt` and optional `web_search`. Returns
        a structured response conforming to `output_schema`.
      type: object
      properties:
        id:
          type: string
          minLength: 1
        type:
          type: string
          enum:
            - ai
        model:
          type: string
          minLength: 1
        user_prompt:
          type: string
        web_search:
          type: boolean
        output_schema:
          type: object
          additionalProperties: true
          description: >-
            A JSONSchema object (Draft-07-compatible). Validated at runtime by
            Ajv.
        conditions:
          $ref: '#/components/schemas/JourneyConditionsField'
      required:
        - type
        - output_schema
    JourneyThrottleStaticNode:
      title: Throttle (Static)
      description: >-
        Throttle the journey by a static `scope` (`user` or `global`), allowing
        at most `max_allowed` invocations per `period`.
      type: object
      properties:
        id:
          type: string
          minLength: 1
        type:
          type: string
          enum:
            - throttle
        scope:
          type: string
          enum:
            - user
            - global
        max_allowed:
          type: integer
          minimum: 1
        period:
          type: string
          minLength: 1
        conditions:
          $ref: '#/components/schemas/JourneyConditionsField'
      required:
        - type
        - scope
        - max_allowed
        - period
    JourneyThrottleDynamicNode:
      title: Throttle (Dynamic)
      description: >-
        Throttle the journey by a dynamic `throttle_key`, allowing at most
        `max_allowed` invocations per `period`.
      type: object
      properties:
        id:
          type: string
          minLength: 1
        type:
          type: string
          enum:
            - throttle
        scope:
          type: string
          enum:
            - dynamic
        max_allowed:
          type: integer
          minimum: 1
        period:
          type: string
          minLength: 1
        throttle_key:
          type: string
          minLength: 1
        conditions:
          $ref: '#/components/schemas/JourneyConditionsField'
      required:
        - type
        - scope
        - max_allowed
        - period
        - throttle_key
    JourneyBatchNode:
      title: Batch
      description: >-
        Collect events arriving at the node into a single batch and fire one
        downstream step with the aggregated payload. The first event into a
        batch owns the run; later contributing events terminate at the batch
        step. The batch releases when any of `max_items` is reached, a quiet
        window of `wait_period` elapses, or the `max_wait_period` ceiling hits.
      type: object
      properties:
        id:
          type: string
          minLength: 1
        type:
          type: string
          enum:
            - batch
        scope:
          type: string
          enum:
            - user
        wait_period:
          type: string
          minLength: 1
          description: >-
            ISO 8601 duration. Quiet window that releases the batch when it
            elapses with no new contributing events. Must be less than
            `max_wait_period`.
        max_wait_period:
          type: string
          minLength: 1
          description: >-
            ISO 8601 duration. Hard ceiling from the first event into the batch;
            releases the batch unconditionally when it elapses.
        max_items:
          type: integer
          default: 100
          minimum: 1
          maximum: 1000
          description: Releases the batch once this many events have been collected.
        retain:
          type: object
          description: >-
            How to select which collected events to retain in the aggregated
            payload when the batch releases.
          properties:
            type:
              type: string
              enum:
                - first
                - last
                - highest
                - lowest
            count:
              type: integer
              minimum: 0
              maximum: 25
            sort_key:
              type: string
              minLength: 1
              description: >-
                Dot-path into the event payload (e.g. `data.priority`). Required
                when `type` is `highest` or `lowest`.
          required:
            - type
            - count
        category_key:
          type: string
          minLength: 1
          maxLength: 256
          description: >-
            Optional partition key. Events with the same `category_key` are
            batched together; events with different values are batched
            separately.
        conditions:
          $ref: '#/components/schemas/JourneyConditionsField'
      required:
        - type
        - scope
        - wait_period
        - max_wait_period
        - retain
    JourneyExitNode:
      title: Exit
      description: Terminate the journey run.
      type: object
      properties:
        id:
          type: string
          minLength: 1
        type:
          type: string
          enum:
            - exit
      required:
        - type
    JourneyConditionsField:
      description: >-
        Condition spec for a journey node. Accepts a single condition atom, an
        AND/OR group, or an AND/OR nested group. Omit the `conditions` property
        entirely to express "no conditions".
      anyOf:
        - $ref: '#/components/schemas/JourneyConditionAtom'
        - $ref: '#/components/schemas/JourneyConditionGroup'
        - $ref: '#/components/schemas/JourneyConditionNestedGroup'
    JourneyMergeStrategy:
      description: Strategy for merging a fetch response into the journey run state.
      type: string
      enum:
        - overwrite
        - soft-merge
        - replace
        - none
    JourneyConditionAtom:
      title: Single condition
      description: >-
        A single condition expressed as a positional tuple of strings.

        - Binary form (3 elements): `[path, operator, value]` where `operator`
          is one of `is equal`, `is not equal`, `contains`, `does not contain`,
          `starts with`, `ends with`, `greater than`, `greater than or equal`,
          `less than`, `less than or equal`.

          Example: `["user.tier", "is equal", "gold"]`.

        - Unary form (2 elements): `[path, operator]` where `operator` is
          one of `exists`, `does not exist`.

          Example: `["user.email", "exists"]`.

        The first element is a non-empty dot-path. The second element is the
        operator (must come from one of the two operator sets above). For the
        binary form, the third element is the comparison value (string). Runtime
        validation of the operator value and arity is performed by the backend;
        SDKs surface this as a string list.
      type: array
      minItems: 2
      maxItems: 3
      items:
        type: string
    JourneyConditionGroup:
      title: Condition group
      type: object
      description: >-
        A leaf condition group. Exactly one of `AND` or `OR` must be present at
        runtime; each is a list of `JourneyConditionAtom` tuples.
      properties:
        AND:
          type: array
          minItems: 2
          items:
            $ref: '#/components/schemas/JourneyConditionAtom'
        OR:
          type: array
          minItems: 2
          items:
            $ref: '#/components/schemas/JourneyConditionAtom'
    JourneyConditionNestedGroup:
      title: Nested condition group
      type: object
      description: >-
        A nested condition group. Exactly one of `AND` or `OR` must be present
        at runtime; each is a list of `JourneyConditionGroup` items.
      properties:
        AND:
          type: array
          minItems: 2
          items:
            $ref: '#/components/schemas/JourneyConditionGroup'
        OR:
          type: array
          minItems: 2
          items:
            $ref: '#/components/schemas/JourneyConditionGroup'
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer

````