openapi: 3.2.0 info: version: 1.0.0 title: Customer.io Journeys API Reference Folders API description: Customer.io provides REST APIs to send real-time customer data, retrieve data from your account, and trigger messages. servers: - url: https://track.customer.io description: The base URL for the Track API. Track endpoints use basic authentication with your Site ID as the user name and your secret key as the password. - url: https://track-eu.customer.io description: The base URL for the Track API (EU region). Track endpoints use basic authentication with your Site ID as the user name and your secret key as the password. - url: https://api.customer.io description: The base URL for broadcasts, transactional messages, and data-retrieval APIs. These endpoints use bearer authorization, and require a [token that you generate in the UI](https://fly.customer.io/settings/api_credentials?keyType=app). - url: https://api-eu.customer.io description: The base URL for broadcasts, transactional messages, and data-retrieval APIs (EU region). These endpoints use bearer authorization, and require a [token that you generate in the UI](https://fly.customer.io/settings/api_credentials?keyType=app). tags: - name: Folders description: Folders organize your Design Studio files. Use these endpoints to list, create, rename, move, and delete folders. Folders hold emails, SMS, and components, but these endpoints return folders only; list the emails, SMS, or components in a folder with their own endpoints. paths: /v1/design_studio/folders: servers: - url: https://api.customer.io description: The base URL for the Design Studio API. These endpoints use bearer authorization, and require an [App API Key that you generate in the UI](https://fly.customer.io/settings/api_credentials?keyType=app). - url: https://api-eu.customer.io description: The base URL for the Design Studio API (EU region). These endpoints use bearer authorization, and require an [App API Key that you generate in the UI](https://fly.customer.io/settings/api_credentials?keyType=app). get: tags: - Folders summary: List folders operationId: listFolders security: - Bearer-Auth: [] description: Returns a paginated list of folders. This does not include files like emails, components, etc. parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/ParentFolderID' - $ref: '#/components/parameters/DirectDescendantsOnly' - $ref: '#/components/parameters/SortBy' - $ref: '#/components/parameters/SortOrder' - $ref: '#/components/parameters/CreatedBefore' - $ref: '#/components/parameters/CreatedAfter' - $ref: '#/components/parameters/UpdatedBefore' - $ref: '#/components/parameters/UpdatedAfter' responses: '200': description: Successful response content: application/json: schema: type: object properties: folders: type: array items: $ref: '#/components/schemas/Folder' meta: $ref: '#/components/schemas/ListMeta' '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' example: errors: - detail: invalid query parameter status: '400' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' post: tags: - Folders summary: Create a folder description: Create a new folder at the root level or under a parent folder. To create a child folder, you need the UUID of the parent folder, which you can retrieve with List folders. operationId: createFolder security: - Bearer-Auth: [] requestBody: required: true content: application/json: schema: type: object required: - name properties: name: type: string description: 'The name of the folder. Cannot contain these characters: < > : " / \ | ? * . ' minLength: 1 maxLength: 170 example: Product Announcements parent_folder_id: type: - string - 'null' description: UUID of the parent folder. Omit or pass `null` to create at root. format: uuid responses: '200': description: Folder created content: application/json: schema: type: object properties: folder: $ref: '#/components/schemas/Folder' '400': description: Bad request content: application/json: schema: type: object properties: errors: type: array items: type: object properties: detail: description: The name is missing or invalid, the parent folder id is an empty string, or there's an unknown JSON field in the request body type: string status: description: Response code type: string example: errors: - detail: missing or invalid name status: '400' '401': $ref: '#/components/responses/Unauthorized' '404': description: Response not found content: application/json: schema: $ref: '#/components/schemas/Error' example: errors: - detail: parent folder not found status: '404' /v1/design_studio/folders/{id}: servers: - url: https://api.customer.io description: The base URL for the Design Studio API. These endpoints use bearer authorization, and require an [App API Key that you generate in the UI](https://fly.customer.io/settings/api_credentials?keyType=app). - url: https://api-eu.customer.io description: The base URL for the Design Studio API (EU region). These endpoints use bearer authorization, and require an [App API Key that you generate in the UI](https://fly.customer.io/settings/api_credentials?keyType=app). get: tags: - Folders summary: Get a folder description: Get a folder by its UUID. You can retrieve the UUID of folders through List folders. operationId: getFolder security: - Bearer-Auth: [] parameters: - $ref: '#/components/parameters/folder_id' responses: '200': description: Successful response content: application/json: schema: type: object properties: folder: $ref: '#/components/schemas/Folder' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' put: tags: - Folders summary: Update a folder description: 'Update part of a folder: the name and/or the folder it belongs to. If you move a folder, all files stay nested in the folder.' operationId: updateFolder security: - Bearer-Auth: [] parameters: - $ref: '#/components/parameters/folder_id' requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: 'Name of the folder. Cannot contain any of these characters: < > : " / \ | ? * . ' minLength: 1 maxLength: 170 parent_folder_id: $ref: '#/components/schemas/parent_folder_id' responses: '204': description: Successful response, no content returned '400': description: Bad request content: application/json: schema: type: object properties: errors: type: array items: type: object properties: detail: description: 'Possible reasons for error: No fields provided, invalid name, parent_folder_id is an empty string or not a valid place to move the folder to, or unknown JSON field in request body ' type: string status: description: Response code type: string example: errors: - detail: missing or invalid name status: '400' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' delete: tags: - Folders summary: Delete a folder description: 'Delete a folder **including subfolders and all file (components, templates, and emails)**. You cannot delete a folder with emails used in your workflows (automations, broadcasts, etc). However, you can delete a folder with components that are referenced in emails linked to workflows, so make sure deleting a folder with components won''t break your emails.' operationId: deleteFolder security: - Bearer-Auth: [] parameters: - $ref: '#/components/parameters/folder_id' responses: '204': description: Successful response, no content returned '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' components: parameters: SortBy: name: sort_by in: query schema: type: string enum: - created - updated - name default: created Limit: name: limit in: query description: The maximum number of results per page. schema: type: integer minimum: 1 maximum: 10000 default: 1000 UpdatedAfter: name: updated_after in: query schema: type: integer format: Unix timestamp description: Return records updated after this time. Must be a unix timestamp. example: 1773856017 CreatedAfter: name: created_after in: query schema: type: integer format: Unix timestamp description: Return records created after this time. Must be a unix timestamp. example: 1773856017 UpdatedBefore: name: updated_before in: query schema: type: integer format: Unix timestamp description: Return records updated before this time. Must be a unix timestamp. example: 1773856017 Page: name: page in: query description: The page number of results you want to display. Use with `limit`. schema: type: integer minimum: 1 default: 1 ParentFolderID: name: parent_folder_id in: query schema: type: string format: uuid description: 'Filter by parent folder. Must reference an existing folder. If not set, the response filters by the root level directory. To list only items in the root folder, leave `parent_folder_id` unset and only set `direct_descendants_only` to `true`. ' CreatedBefore: name: created_before in: query schema: type: integer format: Unix timestamp description: Return records created before this time. Must be a unix timestamp. example: 1773856017 DirectDescendantsOnly: name: direct_descendants_only in: query description: When `true`, the response includes only the immediate children of the parent folder. When `false`, it includes the parent folder's entire subtree. schema: type: boolean default: false SortOrder: name: sort_order in: query schema: type: string enum: - asc - desc default: asc folder_id: name: id in: path required: true description: The UUID of the folder. schema: type: string format: uuid schemas: Error: type: object description: An error response containing one or more error details. properties: errors: type: array description: A list of errors that occurred while processing the request. items: type: object properties: detail: type: string description: A human-readable description of the error. status: type: string description: The HTTP status code for this error, as a string. source: type: object description: The request field that caused the error. Validation errors (`422`) include it. properties: pointer: type: string description: The path to the field that failed, like `/data/attributes/content`. meta: type: object description: Additional detail about the error, when there is any. A failed publish uses this to list Liquid errors per language. parent_folder_id: type: - string - 'null' format: uuid description: 'The UUID of the parent folder. Omit if you want no change to where the folder or file is located. Include `null` to move it to your root directory. Or add the UUID of another folder to move it there. ' ListMeta: type: object properties: pagination: type: object properties: page: type: integer description: The page number of results you're on. limit: type: integer description: The number of results per page. total: type: integer description: The total number of folders. filters: type: object description: The filters applied in your request. example: parent_folder_id: 123e4567-e89b-12d3-a456-426614174000 direct_descendants_only: true sort_by: created sort_order: desc created_before: 1714732800 created_after: null updated_before: null updated_after: null Folder: type: object properties: id: type: string format: uuid description: ID of folder name: type: string description: The name of the folder. parent_folder_id: type: - string - 'null' format: uuid description: The ID of the parent folder. Returns `null` if there is no parent, which means the folder is in the root directory. created: type: integer format: Unix timestamp description: Timestamp of when the folder was created. updated: type: integer format: Unix timestamp description: Timestamp of last update to the folder. example: id: 123e4567-e89b-12d3-a456-426614174000 name: Product Announcements parent_folder_id: null created: 1714732800 updated: 1714732800 responses: Conflict: description: Conflict - linked resource or other constraint violation content: application/json: schema: $ref: '#/components/schemas/Error' example: errors: - detail: a constraint violation prevents this operation status: '409' NotFound: description: The requested resource was not found. content: application/json: schema: $ref: '#/components/schemas/Error' example: errors: - detail: resource not found status: '404' Unauthorized: description: Authentication failed due to a missing or invalid API key. content: application/json: schema: $ref: '#/components/schemas/Error' example: errors: - detail: unauthorized status: '401' securitySchemes: Tracking-API-Key: type: http scheme: basic description: 'The Track API uses a basic authentication scheme. Your credentials are your **Site ID** and your **API key**, **Base-64 encoded** in the format `site_id:api_key`. You can find your Site ID and API key on the [Track API Keys page](https://fly.customer.io/settings/api_credentials). ' Bearer-Auth: type: http scheme: bearer description: 'The App API uses a bearer authentication scheme. You can generate a bearer token, known as an **App API Key**, with a defined scope in [your account settings](https://fly.customer.io/settings/api_credentials?keyType=app). [Learn more about bearer authorization in Customer.io](/accounts/settings/managing-credentials). ' ServiceAccount-Auth: x-scalar-ignore: true type: http scheme: bearer bearerFormat: sa_live_ description: 'Transactional send endpoints (`/v1/send/email`, `/v1/send/push`, `/v1/send/sms`, `/v1/send/whatsapp`, `/v1/send/in_app`, `/v1/send/inbox_message`) also accept a service-account bearer token, prefixed with `sa_live_`. Service-account tokens work across workspaces, so you must pass the target workspace as the `X-Workspace-Id` header on each request. Service-account tokens are intended for testing and one-off sends—for example, using the Customer.io CLI with an AI agent like Claude to verify that a transactional message renders correctly before wiring it into your production backend. **For the production integration that triggers the message from your application, use an App API Key instead**: it''s workspace-scoped, easier to rotate, and has a smaller blast radius. Service-account tokens are server-side credentials. Treat them like any API key—keep them in environment variables or a secret manager, and never embed them in client-side code, mobile apps, or other untrusted contexts. ' bearerAuth: type: http scheme: bearer description: API key passed as a Bearer token. x-tagGroups: - name: Track API v2 tags: - track_v2 - Object Schemas - Person Schemas - Deliveries - name: Track API tags: - trackOverview - trackJsOrBackend - trackLimit - trackRegion - Track Customers - Track Events - Forms - Track Segments - Track v1 Overview - name: App API tags: - appOverview - appLimit - appAuth - Activities - Automations - Broadcasts - Collections - Customers - Data Index - ESP Suppression - Exports - Imports - Info - Live Notifications - Messages - Newsletters - Opt-outs - Reporting Webhooks - Segments - Sender Identities - Snippets - Subscription Center - Transactional - Workspaces - Send Messages - Objects - Newsletter Variants - Newsletter Metrics - Assets - name: Design Studio API tags: - Folders - Components - Emails - Email link and publish - Email testing - SMS - SMS link and publish