# Create a macro

You can create a macro in your workspace, choose who can see it, and add actions that run on the conversation when a teammate uses it.
Send the content as either `body` or `blocks`, not both. `body` takes the same HTML that [Retrieve a macro](/docs/references/preview/rest-api/api.intercom.io/macros/getmacro) returns, including `<attribute key="..." default="..."/>` placeholders, so you can copy a macro by sending its `body` back unchanged. If the HTML holds content that a macro can't store as written, such as a horizontal rule, the request fails with an `unsupported_html` error and no macro is created.
The access token must belong to a teammate who can manage and create macros. OAuth tokens must have the `read_write_macros` scope.

Endpoint: POST /macros
Version: Preview
Security: bearerAuth

## Header parameters:

  - `Intercom-Version` (string)

## Request fields (application/json):

  - `name` (string, required)
    The name of the macro.
    Example: Password reset

  - `body` (string)
    The content of the macro as HTML, in the format the macro's `body` field returns. Write placeholders as `<attribute key="first_name" default="there"/>`. Up to 20,480 bytes.
    Example: <p>Hi <attribute key="first_name" default="there"/>, your order is on its way.</p>

  - `blocks` (array)
    The content of the macro as blocks. Up to 64 KB once serialized.
    Example: [{"type":"paragraph","text":"Hi {{first_name | fallback: \"there\"}}, you can reset your password from the sign-in page."}]

  - `blocks.type` (string, required)
    The type of block.
    Enum: "paragraph", "heading", "subheading", "unorderedList", "orderedList", "code", "button", "image", "video"

  - `blocks.text` (string)
    The text of the block.
    Example: Thanks for getting in touch.

  - `blocks.align` (string)
    The alignment of the block's text.
    Enum: "left", "center", "right", "justify"

  - `blocks.items` (array)
    The items of the list.
    Example: ["Sign out","Clear your cache","Sign back in"]

  - `blocks.linkUrl` (string)
    The URL the button or image links to.
    Example: https://help.example.org/contact

  - `blocks.url` (string)
    The URL of the image. Images from some hosts aren't accepted.
    Example: https://images.example.org/reset-password.png

  - `blocks.width` (integer)
    The width of the image in pixels.
    Example: 600

  - `blocks.height` (integer)
    The height of the image in pixels.
    Example: 400

  - `blocks.provider` (string)
    The video provider, such as `youtube`, `vimeo`, `wistia` or `loom`.
    Example: youtube

  - `blocks.id` (string)
    The unique identifier for the video at its provider.
    Example: a1B2c3D4e5F

  - `visible_to` (string)
    Who can view the macro.
    Enum: "everyone", "specific_teams"

  - `visible_to_team_ids` (array)
    The team IDs that can view the macro. Required when `visible_to` is `specific_teams`. Each team must belong to your workspace.
    Example: ["123456"]

  - `actions` (array)
    The actions applied to the conversation when a teammate uses the macro.
    Example: [{"type":"add-tag-to-conversation","data":{"tag_id":"7890"}}]

  - `actions.type` (string, required)
    The action to apply.
    Enum: "assign-conversation", "assign-conversation-to-owner", "change-conversation-priority", "add-tag-to-conversation", "set-conversation-data-attribute", "close-conversation", "open-conversation", "snooze-conversation", "send-workflow", "workflow-connector-action", "add-conversation-topic", "set-ticket-custom-state"

  - `actions.data` (object)
    The settings for the action. Send `{}` for an action that takes none.
    Example: {"tag_id":"7890"}

  - `actions.data.assignee_id` (string)
    The unique identifier for the teammate or team to assign the conversation to, or `"0"` to unassign it.
    Example: 123

  - `actions.data.priority` (boolean)
    Whether to mark the conversation as priority.
    Example: true

  - `actions.data.tag_id` (string)
    The unique identifier for the tag to add.
    Example: 7890

  - `actions.data.attribute_identifier` (string)
    The unique identifier for the conversation data attribute to set. The attribute must be editable by teammates.
    Example: 15

  - `actions.data.value` (any)
    The value to set the conversation data attribute to.
    Example: Billing

  - `actions.data.snoozed_until` (string)
    When the conversation is snoozed until. `custom_timer` requires `custom_snoozed_until`. `relative` takes `selected_days`, `selected_hours` and `selected_minutes`, and `hours` takes `selected_hours`; for these two, the total must be between 1 minute and 500 days.
    Enum: "later_today", "tomorrow", "monday", "next_week", "next_month", "custom_timer", "relative", "hours"

  - `actions.data.custom_snoozed_until` (string)
    The time to snooze until, as a future ISO 8601 timestamp. Only allowed when `snoozed_until` is `custom_timer`.
    Example: 2026-12-01T09:00:00Z

  - `actions.data.author_timezone` (string)
    The time zone used to work out the snooze time.
    Example: Europe/Dublin

  - `actions.data.selected_days` (integer)
    The number of days to snooze for, counted from when a teammate applies the macro. Only allowed when `snoozed_until` is `relative`.
    Example: 1

  - `actions.data.selected_hours` (integer)
    The number of hours to snooze for, counted from when a teammate applies the macro. Only allowed when `snoozed_until` is `relative` or `hours`.
    Example: 4

  - `actions.data.selected_minutes` (integer)
    The number of minutes to snooze for, counted from when a teammate applies the macro. Only allowed when `snoozed_until` is `relative`.
    Example: 30

  - `actions.data.workflow_instance_id` (string)
    The unique identifier for the workflow to send.
    Example: 2345

  - `actions.data.workflow_connector_action_id` (string)
    The unique identifier for the workflow connector action to run.
    Example: 3456

  - `actions.data.topic_id` (string)
    The unique identifier for the conversation topic to add.
    Example: 4567

  - `actions.data.ticket_custom_state_id` (string)
    The unique identifier for the ticket state to set.
    Example: 5678

## Response 201 fields (application/json):

  - `type` (string)
    String representing the object's type. Always has the value `macro`.
    Enum: "macro"

  - `id` (string)
    The unique identifier for the macro.
    Example: 123

  - `name` (string)
    The name of the macro.
    Example: Order Status Update

  - `body` (string)
    The body of the macro in HTML format with placeholders transformed to XML-like format.
    Example: <p>Hi <attribute key="user.name" default="there"/>, your order is ready!</p>

  - `body_text` (string)
    The plain text version of the macro body with original Intercom placeholder format.
    Example: Hi {{user.name|fallback:"there"}}, your order is ready!

  - `created_at` (string)
    The time the macro was created in ISO 8601 format.
    Example: 2025-07-17T11:18:08.000Z

  - `updated_at` (string)
    The time the macro was last updated in ISO 8601 format.
    Example: 2025-07-17T15:30:24.000Z

  - `visible_to` (string)
    Who can view this macro.
    Enum: "everyone", "specific_teams"

  - `visible_to_team_ids` (array)
    The team IDs that can view this macro when visible_to is set to specific_teams.
    Example: ["456","789"]

  - `available_on` (array)
    Where the macro is available for use.
    Example: ["inbox","messenger"]

  - `actions` (array)
    The actions applied to the conversation when a teammate uses the macro.
    Example: [{"type":"add-tag-to-conversation","data":{"tag_id":"7890"}}]

  - `actions.type` (string, required)
    The action to apply.
    Enum: "assign-conversation", "assign-conversation-to-owner", "change-conversation-priority", "add-tag-to-conversation", "set-conversation-data-attribute", "close-conversation", "open-conversation", "snooze-conversation", "send-workflow", "workflow-connector-action", "add-conversation-topic", "set-ticket-custom-state"

  - `actions.data` (object)
    The settings for the action. Send `{}` for an action that takes none.
    Example: {"tag_id":"7890"}

  - `actions.data.assignee_id` (string)
    The unique identifier for the teammate or team to assign the conversation to, or `"0"` to unassign it.
    Example: 123

  - `actions.data.priority` (boolean)
    Whether to mark the conversation as priority.
    Example: true

  - `actions.data.tag_id` (string)
    The unique identifier for the tag to add.
    Example: 7890

  - `actions.data.attribute_identifier` (string)
    The unique identifier for the conversation data attribute to set. The attribute must be editable by teammates.
    Example: 15

  - `actions.data.value` (any)
    The value to set the conversation data attribute to.
    Example: Billing

  - `actions.data.snoozed_until` (string)
    When the conversation is snoozed until. `custom_timer` requires `custom_snoozed_until`. `relative` takes `selected_days`, `selected_hours` and `selected_minutes`, and `hours` takes `selected_hours`; for these two, the total must be between 1 minute and 500 days.
    Enum: "later_today", "tomorrow", "monday", "next_week", "next_month", "custom_timer", "relative", "hours"

  - `actions.data.custom_snoozed_until` (string)
    The time to snooze until, as a future ISO 8601 timestamp. Only allowed when `snoozed_until` is `custom_timer`.
    Example: 2026-12-01T09:00:00Z

  - `actions.data.author_timezone` (string)
    The time zone used to work out the snooze time.
    Example: Europe/Dublin

  - `actions.data.selected_days` (integer)
    The number of days to snooze for, counted from when a teammate applies the macro. Only allowed when `snoozed_until` is `relative`.
    Example: 1

  - `actions.data.selected_hours` (integer)
    The number of hours to snooze for, counted from when a teammate applies the macro. Only allowed when `snoozed_until` is `relative` or `hours`.
    Example: 4

  - `actions.data.selected_minutes` (integer)
    The number of minutes to snooze for, counted from when a teammate applies the macro. Only allowed when `snoozed_until` is `relative`.
    Example: 30

  - `actions.data.workflow_instance_id` (string)
    The unique identifier for the workflow to send.
    Example: 2345

  - `actions.data.workflow_connector_action_id` (string)
    The unique identifier for the workflow connector action to run.
    Example: 3456

  - `actions.data.topic_id` (string)
    The unique identifier for the conversation topic to add.
    Example: 4567

  - `actions.data.ticket_custom_state_id` (string)
    The unique identifier for the ticket state to set.
    Example: 5678

## Response 400 fields (application/json):

  - `type` (string, required)
    The type is error.list
    Example: error.list

  - `request_id` (string)
    Example: f93ecfa8-d08a-4325-8694-89aeb89c8f85

  - `errors` (array, required)
    An array of one or more error objects

  - `errors.code` (any, required)
    A string indicating the kind of error, used to further qualify the HTTP response code. A few request validation errors send an HTTP status code as an integer here instead, for example `422`.
    Example: unauthorized

  - `errors.message` (string)
    Optional. Human readable description of the error.
    Example: Access Token Invalid

## Response 401 fields (application/json):

  - `type` (string, required)
    The type is error.list
    Example: error.list

  - `request_id` (string)
    Example: f93ecfa8-d08a-4325-8694-89aeb89c8f85

  - `errors` (array, required)
    An array of one or more error objects

  - `errors.code` (any, required)
    A string indicating the kind of error, used to further qualify the HTTP response code. A few request validation errors send an HTTP status code as an integer here instead, for example `422`.
    Example: unauthorized

  - `errors.message` (string)
    Optional. Human readable description of the error.
    Example: Access Token Invalid

## Response 403 fields (application/json):

  - `type` (string, required)
    The type is error.list
    Example: error.list

  - `request_id` (string)
    Example: f93ecfa8-d08a-4325-8694-89aeb89c8f85

  - `errors` (array, required)
    An array of one or more error objects

  - `errors.code` (any, required)
    A string indicating the kind of error, used to further qualify the HTTP response code. A few request validation errors send an HTTP status code as an integer here instead, for example `422`.
    Example: unauthorized

  - `errors.message` (string)
    Optional. Human readable description of the error.
    Example: Access Token Invalid

## Response 422 fields (application/json):

  - `type` (string, required)
    The type is error.list
    Example: error.list

  - `request_id` (string)
    Example: f93ecfa8-d08a-4325-8694-89aeb89c8f85

  - `errors` (array, required)
    An array of one or more error objects

  - `errors.code` (any, required)
    A string indicating the kind of error, used to further qualify the HTTP response code. A few request validation errors send an HTTP status code as an integer here instead, for example `422`.
    Example: unauthorized

  - `errors.message` (string)
    Optional. Human readable description of the error.
    Example: Access Token Invalid

