---
title: "Send an agent reply"
method: POST
path: "/v1/agents/{agentId}/reply"
tags: ["Agents"]
---

# Send an agent reply

`POST /v1/agents/{agentId}/reply`

## Request

- Base URL: `https://api.notifly.io`
- URL: `https://api.notifly.io/v1/agents/{agentId}/reply`
- Auth: API key in header `Authorization`

Send a message or side-effect into an existing agent conversation from your backend.

Use this endpoint when you are not using `@notifly/framework` (for example Python, Go, PHP, .NET, or Java SDKs),
or when a server process outside the bridge needs to post into a live conversation.

**Message actions**
- `reply` — markdown, interactive card, or tool-approval card (optional `files`)
- `edit` — update a previously delivered message in place
- `deleteMessages` — remove rendered platform messages (history is kept)
- `addReactions` — add emoji reactions to existing messages

**Turn control**
- `typing` — `{ status?: string }` to set status, or `"stop"` to clear
- `resolve` — mark the conversation resolved (optionally with a final reply)
- `error: true` — report a customer-runtime failure (cannot combine with other actions)

**Signals & tools**
- `signals` — metadata set/delete/clear, or trigger a Novu workflow
- `toolResults` — persist tool outputs into conversation history
- `toolApprovalRequest` — ledger a gated tool call (pair with an approval card reply)

Returns `{ data: { messageId, platformThreadId } }` when a reply or edit is delivered;
otherwise `{ data: null }`.

## Path parameters

- `agentId` string, required

## Request body

- AgentReplyPayloadDto
  - `conversationId` string, required: Conversation id to reply into. Obtained from the inbound agent event / bridge payload.
  - `integrationIdentifier` string, required: Channel integration identifier linked to the agent for this conversation (e.g. `slack-support`).
  - `reply` union: Outbound message content. Exactly one of `markdown`, `card`, or `toolApprovalCard`. Optional `files` attach to the message. Cannot be combined with `edit`.
    - MarkdownReplyContentDto
      - `markdown` string, required: Plain text or markdown body. Converted to the platform-native format by Novu.
      - `files` FileRefDto[]: Optional attachments (max 15). Each file needs exactly one of data or url.
        - `filename` string, required: Filename shown to the end user, including extension.
        - `mimeType` string: IANA MIME type of the file.
        - `data` string: Base64-encoded inline file bytes. Mutually exclusive with `url`. Decoded size must be ≤ 5 MB. Prefer `url` for larger files.
        - `url` string: Publicly accessible HTTP(S) URL. Mutually exclusive with `data`. Server-side limits: 25 MB per file, 15 files per message, 50 MB aggregate.
    - CardReplyContentDto
      - `card` object, required: Interactive card as a Chat SDK element tree (`type: "card"`). Prefer building with `@notifly/framework` Card helpers when using TypeScript.
      - `files` FileRefDto[]: Optional attachments (max 15). Supported alongside cards on platforms that allow it (e.g. WhatsApp).
        - `filename` string, required: Filename shown to the end user, including extension.
        - `mimeType` string: IANA MIME type of the file.
        - `data` string: Base64-encoded inline file bytes. Mutually exclusive with `url`. Decoded size must be ≤ 5 MB. Prefer `url` for larger files.
        - `url` string: Publicly accessible HTTP(S) URL. Mutually exclusive with `data`. Server-side limits: 25 MB per file, 15 files per message, 50 MB aggregate.
    - ToolApprovalCardReplyContentDto
      - `toolApprovalCard` object, required: Novu tool-approval card descriptor (`type: "tool-approval-card"`). Used with `toolApprovalRequest` to render Approve/Deny UI.
      - `files` FileRefDto[]
        - `filename` string, required: Filename shown to the end user, including extension.
        - `mimeType` string: IANA MIME type of the file.
        - `data` string: Base64-encoded inline file bytes. Mutually exclusive with `url`. Decoded size must be ≤ 5 MB. Prefer `url` for larger files.
        - `url` string: Publicly accessible HTTP(S) URL. Mutually exclusive with `data`. Server-side limits: 25 MB per file, 15 files per message, 50 MB aggregate.
  - `toolApprovalRequest` ToolApprovalRequestPayloadDto
    - `approvalId` string, required: Unique id for this approval request (matches the AI SDK approvalId).
    - `toolCallId` string, required: Id of the tool call awaiting approval.
    - `name` string, required: Name of the gated tool.
    - `input` object: Tool input the model proposed.
    - `approveActionId` string: Server-minted approve action id. When omitted, self-hosted tool-approval:* is minted at persist.
    - `denyActionId` string: Server-minted deny action id. When omitted, self-hosted tool-approval:* is minted at persist.
    - `mcpServerName` string: MCP server name when the gated tool is from an MCP server (for UI labels).
  - `edit` EditPayloadDto
    - `messageId` string, required: Platform message id of the message to edit.
    - `content` union, required: Replacement content. Exactly one of markdown, card, or toolApprovalCard.
      - MarkdownReplyContentDto
        - `markdown` string, required: Plain text or markdown body. Converted to the platform-native format by Novu.
        - `files` FileRefDto[]: Optional attachments (max 15). Each file needs exactly one of data or url.
          - `filename` string, required: Filename shown to the end user, including extension.
          - `mimeType` string: IANA MIME type of the file.
          - `data` string: Base64-encoded inline file bytes. Mutually exclusive with `url`. Decoded size must be ≤ 5 MB. Prefer `url` for larger files.
          - `url` string: Publicly accessible HTTP(S) URL. Mutually exclusive with `data`. Server-side limits: 25 MB per file, 15 files per message, 50 MB aggregate.
      - CardReplyContentDto
        - `card` object, required: Interactive card as a Chat SDK element tree (`type: "card"`). Prefer building with `@notifly/framework` Card helpers when using TypeScript.
        - `files` FileRefDto[]: Optional attachments (max 15). Supported alongside cards on platforms that allow it (e.g. WhatsApp).
          - `filename` string, required: Filename shown to the end user, including extension.
          - `mimeType` string: IANA MIME type of the file.
          - `data` string: Base64-encoded inline file bytes. Mutually exclusive with `url`. Decoded size must be ≤ 5 MB. Prefer `url` for larger files.
          - `url` string: Publicly accessible HTTP(S) URL. Mutually exclusive with `data`. Server-side limits: 25 MB per file, 15 files per message, 50 MB aggregate.
      - ToolApprovalCardReplyContentDto
        - `toolApprovalCard` object, required: Novu tool-approval card descriptor (`type: "tool-approval-card"`). Used with `toolApprovalRequest` to render Approve/Deny UI.
        - `files` FileRefDto[]
          - `filename` string, required: Filename shown to the end user, including extension.
          - `mimeType` string: IANA MIME type of the file.
          - `data` string: Base64-encoded inline file bytes. Mutually exclusive with `url`. Decoded size must be ≤ 5 MB. Prefer `url` for larger files.
          - `url` string: Publicly accessible HTTP(S) URL. Mutually exclusive with `data`. Server-side limits: 25 MB per file, 15 files per message, 50 MB aggregate.
  - `resolve` ResolveDto
    - `summary` string: Optional human-readable resolution summary stored on the conversation.
  - `signals` union[]: Side-effect signals executed during this turn: conversation metadata mutations, Novu workflow triggers, or human-in-the-loop interactions.
    - union
      - MetadataSetSignalDto
        - `type` 'metadata', required
        - `action` 'set': Defaults to `set` when omitted.
        - `key` string, required: Metadata key (1–128 chars; letters, digits, and `-` `_` `:` separators).
        - `value` object, required: JSON-serializable value to store.
      - MetadataDeleteSignalDto
        - `type` 'metadata', required
        - `action` 'delete', required
        - `key` string, required: Metadata key to remove.
      - MetadataClearSignalDto
        - `type` 'metadata', required
        - `action` 'clear', required
      - TriggerSignalDto
        - `type` 'trigger', required
        - `workflowId` string, required: Workflow identifier (same string used with `events.trigger`).
        - `to` union: Recipient(s). Accepts a subscriberId string, subscriber object, topic object, or an array of those. When omitted, Novu falls back to the conversation subscriber.
          - string
          - object
          - union[]
            - union
              - …
        - `payload` object: Arbitrary payload forwarded to the workflow.
      - HumanSignalDto
        - `type` 'human', required
        - `kind` 'ask' | 'approve' | 'choose' | 'tell', required: Interaction verb queued by `ctx.ask` / `ctx.approve` / `ctx.choose` / `ctx.tell`.
        - `prompt` string, required: Question, action description, or one-way message shown to the human.
        - `requestId` string, required: Client-minted id returned by the framework helper; echoed on `ctx.humanResponse.requestId`.
        - `options` string[]: Choice labels — required for `choose`, ignored otherwise.
        - `from` string: Attribution label rendered in the card.
        - `ttlSeconds` number: Seconds until the interaction expires. Default 86400 (24h), max 259200.
        - `to` union: Novu subscriberId(s) allowed to settle this interaction (max 50). First valid answer wins. When omitted, the conversation subscriber is used. Subscriber ids only — not workflow topic recipients.
          - string
          - string[]
  - `toolResults` ToolResultDto[]: Tool-call outcomes to persist in conversation history (typically before the assistant reply).
    - `toolCallId` string, required: Id of the tool call this result resolves.
    - `toolName` string: Name of the tool that produced this result.
    - `output` object: JSON-serializable tool output (or the execution-denied marker).
    - `preview` string: Human-readable preview for the display timeline.
  - `addReactions` AddReactionPayloadDto[]: Emoji reactions to add to existing platform messages.
    - `messageId` string, required: Platform message id to react to.
    - `emojiName` string, required: Well-known cross-platform emoji name (e.g. `white_check_mark`, `thumbsup`).
  - `deleteMessages` DeleteMessagePayloadDto[]: Delete previously posted platform messages. Removes the rendered message only — history is preserved.
    - `messageId` string, required: Platform message id to delete. Removes the rendered message only — history is preserved.
  - `typing` union: Per-turn typing/status control. Pass `{ status?: string }` to set/update the status (omit `status` for "Thinking…"), or `"stop"` to clear it. Best-effort per platform.
    - 'stop': Clear the typing indicator.
    - TypingStatusDto
      - `status` string: Status text shown while the agent works. Omit for the default "Thinking…".
  - `error` boolean: Bridge reports that the customer runtime failed this turn. Cannot be combined with other actions. Novu delivers generic user-facing error copy.

## Response `200`

OK. When a reply or edit is delivered, `data` contains the platform message identifiers. Side-effect-only requests (typing, reactions, deletes, signals without an outbound message) return `data: null`.

- object
  - `data` SentMessageInfoDto
    - `messageId` string, required: Platform-native message id of the delivered or edited message (e.g. Slack `ts`, Teams activity id).
    - `platformThreadId` string, required: Platform-native thread / conversation id where the message was delivered.

## Other responses

- `400`: Bad Request
- `401`: Unauthorized
- `403`: Forbidden
- `404`: The agent or conversation was not found.
- `405`: Method Not Allowed
- `409`: Conflict
- `413`: Payload Too Large
- `414`: URI Too Long
- `415`: Unsupported Media Type
- `422`: Unprocessable Entity
- `429`: The client has sent too many requests in a given amount of time.
- `500`: Internal Server Error
- `503`: The server is currently unable to handle the request due to a temporary overload or scheduled maintenance, which will likely be alleviated after some delay.

---

[API](https://skmtc.dev/notifly/apis/notifly-api.md) · [All operations](https://skmtc.dev/notifly/apis/notifly-api/llms.txt) · [OpenAPI document](https://skmtc.dev/notifly/apis/notifly-api/revisions/af909b9e1e57?raw)
