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

# Send messages

> Send Messenger text and attachments from your Page.

## Send text

```bash theme={null}
curl -X POST "https://gateway.hookmyapp.com/meta/v25.0/${PAGE_ID}/messages" \
  -H "Authorization: Bearer ${PAGE_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
  "recipient": { "id": "200000000000001" },
  "message": { "text": "Hello from my app" }
}'
```

`recipient.id` is the `sender.id` (PSID) from the inbound webhook.<br />
`PAGE_ID` is the Page id from `hookmyapp channels show <channel>` and `PAGE_ACCESS_TOKEN` the channel token from `hookmyapp channels token <channel>`.

## Send an attachment

```bash theme={null}
curl -X POST "https://gateway.hookmyapp.com/meta/v25.0/${PAGE_ID}/messages" \
  -H "Authorization: Bearer ${PAGE_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
  "recipient": { "id": "200000000000001" },
  "message": {
    "attachment": {
      "type": "image",
      "payload": { "url": "https://example.com/photo.jpg", "is_reusable": true }
    }
  }
}'
```

`type` is `image`, `video`, `audio` or `file`. The URL must be public https.

## The 24-hour window

Messenger allows a free-form reply only within 24 hours of the person's last message.<br />
Outside that window the send is rejected with HTTP 409 and the message "This person last messaged you more than 24 hours ago", unless a message tag applies.

Send outside the window with a tag:

```bash theme={null}
curl -X POST "https://gateway.hookmyapp.com/meta/v25.0/${PAGE_ID}/messages" \
  -H "Authorization: Bearer ${PAGE_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
  "recipient": { "id": "200000000000001" },
  "messaging_type": "MESSAGE_TAG",
  "tag": "POST_PURCHASE_UPDATE",
  "message": { "text": "Your order shipped." }
}'
```

Tags Meta accepts today: `CONFIRMED_EVENT_UPDATE`, `POST_PURCHASE_UPDATE`, `ACCOUNT_UPDATE`, and `HUMAN_AGENT` for Pages Meta has approved for it.<br />
Each tag is limited to the kind of update its name describes. Promotional content under a tag gets the Page restricted.

The channel page shows the open windows: each recent sender and whether their 24 hours are still running.

## Mark as seen and typing

```bash theme={null}
curl -X POST "https://gateway.hookmyapp.com/meta/v25.0/${PAGE_ID}/messages" \
  -H "Authorization: Bearer ${PAGE_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{ "recipient": { "id": "200000000000001" }, "sender_action": "mark_seen" }'
```

`sender_action` is `mark_seen`, `typing_on` or `typing_off`. Sender actions are free.

## Reply to a comment in private

Send the commenter a Messenger message instead of a public reply. See [Comments](/facebook/comments#reply-privately).

## Send with the CLI

```bash theme={null}
# Send text
hookmyapp facebook messages send --channel ch_xxxxxxxx --to <psid> --text "hi"

# Send outside the 24-hour window
hookmyapp facebook messages send --channel ch_xxxxxxxx --to <psid> --text "Your order shipped" --tag POST_PURCHASE_UPDATE

# Complete body, verbatim
hookmyapp facebook messages send --channel ch_xxxxxxxx --body @msg.json

# Mark as seen
hookmyapp facebook messages read --channel ch_xxxxxxxx --to <psid>
```

## Send with MCP

`send_message` accepts a Facebook channel. Pass the PSID as the recipient.

```text theme={null}
Use HookMyApp MCP to reply "Thanks, we will get back to you today" to the last Messenger message on Facebook channel ch_xxxxxxxx.
```

## Next steps

* [Receive webhooks](/facebook/receive-webhooks): Get the PSID from the inbound message.
* [Inbox](/facebook/inbox): Read the conversation before you reply.
