# Send peer-to-peer message (/en/api-reference/api-ref/signaling/peer-to-peer-message)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

Sends a peer-to-peer Signaling message from the server.

- OpenAPI: /openapi/rtm/signaling-rest.en.yaml
- Operation ID: send-peer-message
- Method: POST
- Path: /{appid}/rtm/users/{user_id}/peer_messages
- Endpoint: https://api.agora.io/dev/v2/project/{appid}/rtm/users/{user_id}/peer_messages

## Servers

- https://api.agora.io/dev/v2/project

Sends a peer-to-peer message from the server. The user sending the message does not have to log in to Signaling.

- You can send peer-to-peer or channel messages with any user ID when using basic HTTP authentication.
- When you use token authentication, you may send peer-to-peer or channel messages using only the user ID you used to generate the Signaling token.

For more information about how to generate a Signaling token, see [Secure authentication with tokens](/en/realtime-media/rtm/build/connect-and-authenticate/authentication-workflow).


## Authorization

This endpoint requires authentication.

- `basicAuth`

## Parameters

- `appid` (path, required, string) - The App ID of your Agora project.
- `user_id` (path, required, string) - Signaling user ID to send a peer-to-peer message. It must not exceed 64 characters in length or be an empty string. Since `user_id` is a URL parameter, the first and last characters must not be a space.

  :::info[Note]
  Since `user_id` is a URL parameter, the first character and the last characters must not be a space.
  :::
- `wait_for_ack` (query, optional, boolean) - Whether the API returns the HTTP response after Signaling receives the acknowledgement from the receiver.

- `true`: The API waits for the receiver to acknowledge receipt of
  the message before returning the HTTP response.

- `false`: The API returns the HTTP response immediately after the
  Agora RTM server receives the message, without waiting for
  receiver acknowledgement.
  - Default: `false`

### Request

For more information about how to generate a Signaling token, see Secure authentication with tokens.


## Request body

- `destination` (string, required) - Signaling user ID to receive a peer-to-peer message. It must not exceed 64 characters in length or be an empty string.
- `enable_offline_messaging` (boolean) - Whether to enable offline messages.
- `true`: Enable offline messages. If the receiver is offline when you send a peer-to-peer message, Signaling saves the message (maximum 200 per receiver) and delivers it when the receiver is online.
- `false`: Disable offline messages.
  - Default: `false`

  :::warning[Caution]
  The offline message feature is deprecated and will be removed in a future version. Agora recommends that you do not use it.
  :::
- `enable_historical_messaging` (boolean) - Whether to save as a historical message.

- `true`: Save as a historical message.
- `false`: Do not save as a historical message.
  - Default: `false`
- `payload` (string, required) - Content of the peer-to-peer message. It must not be an empty string or exceed 32 KB in length.

### Request body example

```json
{
  "destination": "userB",
  "enable_offline_messaging": false,
  "enable_historical_messaging": false,
  "payload": "Hello"
}
```

## Request examples

### curl

```bash
curl -X POST 'https://api.agora.io/dev/v2/project/876922cbca0098dff4323566daa89675/rtm/users/userA/peer_messages?wait_for_ack=true' \
      -H 'Content-Type: application/json;charset=utf-8' \
      -H 'Authorization: Basic <your_base64_encoded_credentials>' \
      -d '{
        "destination": "userB",
        "enable_offline_messaging": false,
        "enable_historical_messaging": false,
        "payload": "Hello"
      }'
```

### Python

```python
import requests
    import json

    url = 'https://api.agora.io/dev/v2/project/876922cbca0098dff4323566daa89675/rtm/users/userA/peer_messages?wait_for_ack=true'

    headers = {
      'Content-Type': 'application/json;charset=utf-8',
      'Authorization': 'Basic <your_base64_encoded_credentials>'
    }

    data = {
      "destination": "userB",
      "enable_offline_messaging": False,
      "enable_historical_messaging": False,
      "payload": "Hello"
    }

    try:
      response = requests.post(url, headers=headers, data=json.dumps(data))
      print("Status:", response.status_code)
      print("Response:", response.json())
    except Exception as error:
      print("Error:", error)
```

### Node.js

```javascript
const axios = require('axios');

    const url = 'https://api.agora.io/dev/v2/project/876922cbca0098dff4323566daa89675/rtm/users/userA/peer_messages?wait_for_ack=true';

    const headers = {
    'Content-Type': 'application/json;charset=utf-8',
    'Authorization': 'Basic <your_base64_encoded_credentials>'
    };

    const data = {
    destination: "userB",
    enable_offline_messaging: false,
    enable_historical_messaging: false,
    payload: "Hello"
    };

    axios.post(url, data, { headers })
    .then(response => {
      console.log("Status:", response.status);
      console.log("Response:", response.data);
    })
    .catch(error => {
      console.error("Error:", error.response ? error.response.data : error.message);
    });
```


### Response

- If the returned status code is `200`, the request was successful. The response body contains the result of the request.

- If the returned status code is not `200`, the request failed. The response body includes the error code and description. Refer to [status codes](/en/realtime-media/rtm/reference/error-codes#restful-api-error-codes) to understand the possible reasons for failure.


## Responses

### 200

The request was successful. The response body contains the result of the request.

- `result` (string) - Request result. `success` if the request succeeds, `failed` if it fails.

Request result.

 - success: The request succeeds.
 - failed: The request fails.
- `request_id` (string) - Unique ID to identify this request.
- `code` (string) - Message status: `message_sent`, `message_delivered`, or `message_offline`.

Message status.

 - message_sent: The message is sent.
 - message_delivered: The message is received.
 - message_offline: The receiver is offline.
### default

The request failed. The response body includes the error code and description.

No schema.

## Response examples

### 200

```json
{
  "result": "success",
  "request_id": "123",
  "code": "message_sent"
}
```
