openapi: 3.0.3 info: title: Courier API description: >- Courier is notification infrastructure that orchestrates transactional and product messaging across email, SMS, push, chat, and an in-app inbox from a single REST API. This document models the primary public endpoints under the base URL https://api.courier.com: sending notifications (Send), inspecting sent messages, managing lists, user profiles, preferences, device tokens, notification templates, brands, automations, audiences, tenants, bulk jobs, audit events, and translations. All requests are authenticated with a Bearer API key. Endpoint paths are grounded in Courier's published API reference; request and response bodies are modeled and simplified. version: '2024-01' contact: name: Courier url: https://www.courier.com x-endpoint-confidence: >- Paths and methods are grounded in the Courier API reference (https://www.courier.com/docs/reference). Schemas are modeled, not exhaustive. servers: - url: https://api.courier.com description: Courier production API security: - bearerAuth: [] tags: - name: Send description: Dispatch a notification across channels. - name: Messages description: Inspect, track, cancel, and archive sent messages. - name: Lists description: Subscription lists and their subscribers. - name: User Profiles description: Recipient profiles keyed by your user id. - name: User Preferences description: Per-user, per-topic notification preferences. - name: Device Tokens description: Push notification device tokens for a user. - name: Notification Templates description: Notification templates designed in the Courier studio. - name: Brands description: Reusable logos, colors, and email styling. - name: Automations description: Multi-step notification workflows. - name: Audiences description: Dynamic audiences defined by profile filters. - name: Tenants description: Organizations/accounts for multi-tenant apps. - name: Bulk description: One-to-many sends via jobs. - name: Audit Events description: Workspace audit events. - name: Translations description: Localization strings per domain and locale. paths: /send: post: operationId: sendMessage tags: [Send] summary: Send a message description: >- Dispatches a single notification to one or more recipients, routed across channels using a template or inline content, per-recipient routing, data, and overrides. Returns a requestId used to track the resulting messages. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SendRequest' responses: '202': description: The send request was accepted for processing. content: application/json: schema: type: object properties: requestId: type: string '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' /messages: get: operationId: listMessages tags: [Messages] summary: List messages description: Fetch the statuses of messages you have previously sent. parameters: - name: cursor in: query schema: { type: string } - name: status in: query schema: { type: string } - name: recipient in: query schema: { type: string } responses: '200': description: A paged list of messages. content: application/json: schema: type: object properties: paging: $ref: '#/components/schemas/Paging' results: type: array items: $ref: '#/components/schemas/Message' '401': $ref: '#/components/responses/Unauthorized' /messages/{message_id}: parameters: - $ref: '#/components/parameters/MessageId' get: operationId: getMessage tags: [Messages] summary: Get a message description: Retrieve the status of a single message by id. responses: '200': description: The requested message. content: application/json: schema: $ref: '#/components/schemas/Message' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /messages/{message_id}/content: parameters: - $ref: '#/components/parameters/MessageId' get: operationId: getMessageContent tags: [Messages] summary: Get message content description: Retrieve the rendered content of a message as delivered to each channel. responses: '200': description: The rendered message content. content: application/json: schema: type: object additionalProperties: true '401': $ref: '#/components/responses/Unauthorized' /messages/{message_id}/history: parameters: - $ref: '#/components/parameters/MessageId' get: operationId: getMessageHistory tags: [Messages] summary: Get message history description: >- Retrieve the delivery and engagement history for a message (ENQUEUED, SENT, DELIVERED, OPENED, CLICKED, UNDELIVERABLE, etc.). responses: '200': description: The message history events. content: application/json: schema: type: object properties: results: type: array items: type: object additionalProperties: true '401': $ref: '#/components/responses/Unauthorized' /messages/{message_id}/cancel: parameters: - $ref: '#/components/parameters/MessageId' post: operationId: cancelMessage tags: [Messages] summary: Cancel a message description: Cancel a message that is currently enqueued and not yet delivered. responses: '200': description: The cancelled message. content: application/json: schema: $ref: '#/components/schemas/Message' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /messages/{message_id}/archive: parameters: - $ref: '#/components/parameters/MessageId' put: operationId: archiveMessage tags: [Messages] summary: Archive a message description: Archive a message so it no longer appears in the default message list. responses: '204': description: The message was archived. '401': $ref: '#/components/responses/Unauthorized' /lists: get: operationId: listLists tags: [Lists] summary: Get all lists description: Returns all subscription lists in the workspace, paginated. parameters: - name: cursor in: query schema: { type: string } responses: '200': description: A paged list of lists. content: application/json: schema: type: object properties: paging: $ref: '#/components/schemas/Paging' items: type: array items: $ref: '#/components/schemas/List' '401': $ref: '#/components/responses/Unauthorized' /lists/{list_id}: parameters: - $ref: '#/components/parameters/ListId' get: operationId: getList tags: [Lists] summary: Get a list responses: '200': description: The requested list. content: application/json: schema: $ref: '#/components/schemas/List' '404': $ref: '#/components/responses/NotFound' put: operationId: putList tags: [Lists] summary: Create or replace a list requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ListInput' responses: '200': description: The created or replaced list. content: application/json: schema: $ref: '#/components/schemas/List' delete: operationId: deleteList tags: [Lists] summary: Delete a list responses: '204': description: The list was deleted. /lists/{list_id}/restore: parameters: - $ref: '#/components/parameters/ListId' put: operationId: restoreList tags: [Lists] summary: Restore a deleted list responses: '204': description: The list was restored. /lists/{list_id}/subscriptions: parameters: - $ref: '#/components/parameters/ListId' get: operationId: getListSubscriptions tags: [Lists] summary: Get list subscriptions responses: '200': description: The users subscribed to the list. content: application/json: schema: type: object properties: paging: $ref: '#/components/schemas/Paging' items: type: array items: type: object additionalProperties: true put: operationId: subscribeUsersToList tags: [Lists] summary: Subscribe multiple users to a list requestBody: required: true content: application/json: schema: type: object properties: recipients: type: array items: type: object additionalProperties: true responses: '204': description: The users were subscribed. /lists/{list_id}/subscriptions/{user_id}: parameters: - $ref: '#/components/parameters/ListId' - $ref: '#/components/parameters/UserId' put: operationId: subscribeUserToList tags: [Lists] summary: Subscribe a user to a list responses: '204': description: The user was subscribed. delete: operationId: unsubscribeUserFromList tags: [Lists] summary: Unsubscribe a user from a list responses: '204': description: The user was unsubscribed. /profiles/{user_id}: parameters: - $ref: '#/components/parameters/UserId' get: operationId: getProfile tags: [User Profiles] summary: Get a profile responses: '200': description: The requested profile. content: application/json: schema: $ref: '#/components/schemas/Profile' '404': $ref: '#/components/responses/NotFound' post: operationId: createProfile tags: [User Profiles] summary: Create or merge a profile requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ProfileInput' responses: '200': description: The created profile. content: application/json: schema: $ref: '#/components/schemas/Profile' put: operationId: replaceProfile tags: [User Profiles] summary: Replace a profile requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ProfileInput' responses: '200': description: The replaced profile. content: application/json: schema: $ref: '#/components/schemas/Profile' patch: operationId: patchProfile tags: [User Profiles] summary: Merge/patch a profile requestBody: required: true content: application/json: schema: type: object properties: patch: type: array items: type: object additionalProperties: true responses: '200': description: The patched profile. content: application/json: schema: $ref: '#/components/schemas/Profile' delete: operationId: deleteProfile tags: [User Profiles] summary: Delete a profile responses: '204': description: The profile was deleted. /profiles/{user_id}/lists: parameters: - $ref: '#/components/parameters/UserId' get: operationId: getProfileLists tags: [User Profiles] summary: Get the lists a user is subscribed to responses: '200': description: The subscription lists for the user. content: application/json: schema: type: object properties: paging: $ref: '#/components/schemas/Paging' results: type: array items: $ref: '#/components/schemas/List' /users/{user_id}/preferences: parameters: - $ref: '#/components/parameters/UserId' get: operationId: listUserPreferences tags: [User Preferences] summary: List user preferences description: List a user's notification preferences across subscription topics. responses: '200': description: The user's topic preferences. content: application/json: schema: type: object properties: items: type: array items: $ref: '#/components/schemas/TopicPreference' /users/{user_id}/preferences/{topic_id}: parameters: - $ref: '#/components/parameters/UserId' - name: topic_id in: path required: true schema: { type: string } get: operationId: getUserTopicPreference tags: [User Preferences] summary: Get a user topic preference responses: '200': description: The user's preference for the topic. content: application/json: schema: $ref: '#/components/schemas/TopicPreference' put: operationId: updateUserTopicPreference tags: [User Preferences] summary: Update a user topic preference requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TopicPreference' responses: '204': description: The preference was updated. /users/{user_id}/tokens: parameters: - $ref: '#/components/parameters/UserId' get: operationId: listUserTokens tags: [Device Tokens] summary: List a user's device tokens responses: '200': description: The user's device tokens. content: application/json: schema: type: array items: $ref: '#/components/schemas/DeviceToken' /users/{user_id}/tokens/{token}: parameters: - $ref: '#/components/parameters/UserId' - name: token in: path required: true schema: { type: string } get: operationId: getUserToken tags: [Device Tokens] summary: Get a device token responses: '200': description: The device token. content: application/json: schema: $ref: '#/components/schemas/DeviceToken' put: operationId: putUserToken tags: [Device Tokens] summary: Add or update a device token requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DeviceToken' responses: '204': description: The token was stored. patch: operationId: patchUserToken tags: [Device Tokens] summary: Patch a device token requestBody: required: true content: application/json: schema: type: object additionalProperties: true responses: '204': description: The token was patched. delete: operationId: deleteUserToken tags: [Device Tokens] summary: Delete a device token responses: '204': description: The token was deleted. /notifications: get: operationId: listNotifications tags: [Notification Templates] summary: List notification templates responses: '200': description: A paged list of notification templates. content: application/json: schema: type: object properties: paging: $ref: '#/components/schemas/Paging' results: type: array items: $ref: '#/components/schemas/Notification' /notifications/{notification_id}/content: parameters: - name: notification_id in: path required: true schema: { type: string } get: operationId: getNotificationContent tags: [Notification Templates] summary: Get notification content responses: '200': description: The template content blocks. content: application/json: schema: type: object additionalProperties: true post: operationId: updateNotificationContent tags: [Notification Templates] summary: Update notification content requestBody: required: true content: application/json: schema: type: object additionalProperties: true responses: '204': description: The content was updated. /notifications/{notification_id}/draft/submit: parameters: - name: notification_id in: path required: true schema: { type: string } put: operationId: submitNotificationDraft tags: [Notification Templates] summary: Submit a notification draft for publishing responses: '204': description: The draft was submitted. /brands: get: operationId: listBrands tags: [Brands] summary: List brands responses: '200': description: A paged list of brands. content: application/json: schema: type: object properties: paging: $ref: '#/components/schemas/Paging' results: type: array items: $ref: '#/components/schemas/Brand' post: operationId: createBrand tags: [Brands] summary: Create a brand requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BrandInput' responses: '200': description: The created brand. content: application/json: schema: $ref: '#/components/schemas/Brand' /brands/{brand_id}: parameters: - name: brand_id in: path required: true schema: { type: string } get: operationId: getBrand tags: [Brands] summary: Get a brand responses: '200': description: The requested brand. content: application/json: schema: $ref: '#/components/schemas/Brand' '404': $ref: '#/components/responses/NotFound' put: operationId: replaceBrand tags: [Brands] summary: Replace a brand requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BrandInput' responses: '200': description: The replaced brand. content: application/json: schema: $ref: '#/components/schemas/Brand' delete: operationId: deleteBrand tags: [Brands] summary: Delete a brand responses: '204': description: The brand was deleted. /automations/invoke: post: operationId: invokeAdHocAutomation tags: [Automations] summary: Invoke an ad-hoc automation description: Invoke an automation run defined inline in the request body. requestBody: required: true content: application/json: schema: type: object properties: automation: type: object additionalProperties: true brand: type: string data: type: object additionalProperties: true profile: type: object additionalProperties: true recipient: type: string template: type: string responses: '202': description: The automation run was accepted. content: application/json: schema: type: object properties: runId: type: string /automations/{template_id}/invoke: parameters: - name: template_id in: path required: true schema: { type: string } post: operationId: invokeAutomationTemplate tags: [Automations] summary: Invoke an automation template requestBody: required: true content: application/json: schema: type: object additionalProperties: true responses: '202': description: The automation template run was accepted. content: application/json: schema: type: object properties: runId: type: string /audiences: get: operationId: listAudiences tags: [Audiences] summary: List audiences responses: '200': description: A paged list of audiences. content: application/json: schema: type: object properties: paging: $ref: '#/components/schemas/Paging' items: type: array items: $ref: '#/components/schemas/Audience' /audiences/{audience_id}: parameters: - name: audience_id in: path required: true schema: { type: string } get: operationId: getAudience tags: [Audiences] summary: Get an audience responses: '200': description: The requested audience. content: application/json: schema: $ref: '#/components/schemas/Audience' '404': $ref: '#/components/responses/NotFound' put: operationId: putAudience tags: [Audiences] summary: Create or update an audience requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AudienceInput' responses: '200': description: The created or updated audience. content: application/json: schema: $ref: '#/components/schemas/Audience' delete: operationId: deleteAudience tags: [Audiences] summary: Delete an audience responses: '204': description: The audience was deleted. /audiences/{audience_id}/members: parameters: - name: audience_id in: path required: true schema: { type: string } get: operationId: listAudienceMembers tags: [Audiences] summary: List audience members responses: '200': description: The members currently matching the audience. content: application/json: schema: type: object properties: paging: $ref: '#/components/schemas/Paging' items: type: array items: type: object additionalProperties: true /tenants: get: operationId: listTenants tags: [Tenants] summary: List tenants responses: '200': description: A paged list of tenants. content: application/json: schema: type: object properties: has_more: type: boolean items: type: array items: $ref: '#/components/schemas/Tenant' /tenants/{tenant_id}: parameters: - name: tenant_id in: path required: true schema: { type: string } get: operationId: getTenant tags: [Tenants] summary: Get a tenant responses: '200': description: The requested tenant. content: application/json: schema: $ref: '#/components/schemas/Tenant' '404': $ref: '#/components/responses/NotFound' put: operationId: putTenant tags: [Tenants] summary: Create or replace a tenant requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TenantInput' responses: '200': description: The created or replaced tenant. content: application/json: schema: $ref: '#/components/schemas/Tenant' delete: operationId: deleteTenant tags: [Tenants] summary: Delete a tenant responses: '204': description: The tenant was deleted. /tenants/{tenant_id}/users: parameters: - name: tenant_id in: path required: true schema: { type: string } get: operationId: listTenantUsers tags: [Tenants] summary: List users in a tenant responses: '200': description: The users associated with the tenant. content: application/json: schema: type: object properties: has_more: type: boolean items: type: array items: type: object additionalProperties: true /bulk: post: operationId: createBulkJob tags: [Bulk] summary: Create a bulk job requestBody: required: true content: application/json: schema: type: object properties: message: $ref: '#/components/schemas/InboundBulkMessage' responses: '200': description: The created bulk job. content: application/json: schema: type: object properties: jobId: type: string /bulk/{job_id}: parameters: - $ref: '#/components/parameters/JobId' get: operationId: getBulkJob tags: [Bulk] summary: Get a bulk job responses: '200': description: The bulk job status. content: application/json: schema: type: object additionalProperties: true post: operationId: addUsersToBulkJob tags: [Bulk] summary: Add users to a bulk job requestBody: required: true content: application/json: schema: type: object properties: users: type: array items: type: object additionalProperties: true responses: '204': description: The users were added. /bulk/{job_id}/run: parameters: - $ref: '#/components/parameters/JobId' post: operationId: runBulkJob tags: [Bulk] summary: Run a bulk job responses: '202': description: The bulk job started running. /bulk/{job_id}/users: parameters: - $ref: '#/components/parameters/JobId' get: operationId: listBulkJobUsers tags: [Bulk] summary: List users in a bulk job responses: '200': description: The users in the bulk job. content: application/json: schema: type: object properties: items: type: array items: type: object additionalProperties: true /audit-events: get: operationId: listAuditEvents tags: [Audit Events] summary: List audit events responses: '200': description: A paged list of audit events. content: application/json: schema: type: object properties: paging: $ref: '#/components/schemas/Paging' results: type: array items: $ref: '#/components/schemas/AuditEvent' /audit-events/{audit_event_id}: parameters: - name: audit_event_id in: path required: true schema: { type: string } get: operationId: getAuditEvent tags: [Audit Events] summary: Get an audit event responses: '200': description: The requested audit event. content: application/json: schema: $ref: '#/components/schemas/AuditEvent' '404': $ref: '#/components/responses/NotFound' /translations/{domain}/{locale}: parameters: - name: domain in: path required: true schema: { type: string } - name: locale in: path required: true schema: { type: string } get: operationId: getTranslation tags: [Translations] summary: Get translations for a locale description: Retrieve the translation (.po) content for a domain and locale. responses: '200': description: The translation content. content: text/plain: schema: type: string put: operationId: updateTranslation tags: [Translations] summary: Update translations for a locale requestBody: required: true content: text/plain: schema: type: string responses: '204': description: The translation was updated. components: securitySchemes: bearerAuth: type: http scheme: bearer description: >- Courier API key passed as `Authorization: Bearer `. Keys are found in the Courier settings under API Keys and are environment scoped (test vs production). parameters: MessageId: name: message_id in: path required: true schema: { type: string } ListId: name: list_id in: path required: true schema: { type: string } UserId: name: user_id in: path required: true description: Your application's user id for the recipient. schema: { type: string } JobId: name: job_id in: path required: true schema: { type: string } responses: BadRequest: description: The request was malformed or failed validation. content: application/json: schema: $ref: '#/components/schemas/Error' Unauthorized: description: Missing or invalid API key. content: application/json: schema: $ref: '#/components/schemas/Error' NotFound: description: The requested resource was not found. content: application/json: schema: $ref: '#/components/schemas/Error' schemas: Error: type: object properties: message: type: string type: type: string Paging: type: object properties: cursor: type: string more: type: boolean SendRequest: type: object required: - message properties: message: type: object description: The message to send. properties: to: description: One recipient object or an array of recipients. oneOf: - $ref: '#/components/schemas/Recipient' - type: array items: $ref: '#/components/schemas/Recipient' template: type: string description: The notification template id to send. content: type: object description: Inline elemental content to send instead of a template. additionalProperties: true brand_id: type: string data: type: object additionalProperties: true routing: type: object properties: method: type: string enum: [all, single] channels: type: array items: type: string channels: type: object additionalProperties: true providers: type: object additionalProperties: true metadata: type: object additionalProperties: true Recipient: type: object properties: user_id: type: string email: type: string phone_number: type: string list_id: type: string audience_id: type: string tenant_id: type: string data: type: object additionalProperties: true preferences: type: object additionalProperties: true Message: type: object properties: id: type: string status: type: string enum: - ENQUEUED - SENT - DELIVERED - OPENED - CLICKED - UNMAPPED - UNROUTABLE - UNDELIVERABLE - CANCELED enqueued: type: integer sent: type: integer delivered: type: integer opened: type: integer clicked: type: integer recipient: type: string notification: type: object additionalProperties: true ListInput: type: object required: [name] properties: name: type: string List: allOf: - $ref: '#/components/schemas/ListInput' - type: object properties: id: type: string created: type: integer updated: type: integer ProfileInput: type: object properties: profile: type: object additionalProperties: true Profile: type: object properties: profile: type: object additionalProperties: true TopicPreference: type: object properties: topic_id: type: string status: type: string enum: [OPTED_IN, OPTED_OUT, REQUIRED] has_custom_routing: type: boolean custom_routing: type: array items: type: string DeviceToken: type: object properties: token: type: string provider_key: type: string enum: [apn, firebase-fcm, expo, onesignal] device: type: object additionalProperties: true status: type: string enum: [active, failed, revoked, unknown] Notification: type: object properties: id: type: string title: type: string topic_id: type: string tags: type: object additionalProperties: true BrandInput: type: object required: [name] properties: name: type: string settings: type: object additionalProperties: true snippets: type: object additionalProperties: true Brand: allOf: - $ref: '#/components/schemas/BrandInput' - type: object properties: id: type: string version: type: string created: type: integer updated: type: integer AudienceInput: type: object properties: name: type: string description: type: string filter: type: object additionalProperties: true Audience: allOf: - $ref: '#/components/schemas/AudienceInput' - type: object properties: id: type: string created_at: type: string updated_at: type: string TenantInput: type: object required: [name] properties: name: type: string parent_tenant_id: type: string default_preferences: type: object additionalProperties: true properties: type: object additionalProperties: true brand_id: type: string Tenant: allOf: - $ref: '#/components/schemas/TenantInput' - type: object properties: id: type: string InboundBulkMessage: type: object properties: template: type: string brand: type: string data: type: object additionalProperties: true event: type: string locale: type: object additionalProperties: true AuditEvent: type: object properties: auditEventId: type: string source: type: string type: type: string timestamp: type: string actor: type: object additionalProperties: true target: type: object additionalProperties: true