This document specifies an Application Programming Interface (API) that is RECOMMENDED for developers of the [WAKU2](https://github.com/vacp2p/rfc-index/blob/7b443c1aab627894e3f22f5adfbb93f4c4eac4f6/waku/standards/core/10/waku2.md) clients to implement,
and for consumers to use as a single entry point to its functionalities.
This document defines the specifications and guidelines necessary for implementing the API,
ensuring interoperability and consistency across the Waku protocol family.
## Design Requirements
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”,
“RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in [RFC2119](https://www.ietf.org/rfc/rfc2119.txt).
### Definitions
This section defines key terms and concepts used throughout this document.
Each term is detailed in dedicated subsections to ensure clarity and consistency in interpretation.
`Multiaddr` - a self-describing format for encoding network address of a remote peer as per [libp2p addressing](https://github.com/libp2p/specs/blob/6d38f88f7b2d16b0e4489298bcd0737a6d704f7e/addressing/README.md) specification.
### Motivation
Real-world application development has exposed challenges in achieving comprehensive usability guarantees for core Waku protocols.
- Employ [LIGHTPUSH](../standards/core/lightpush.md) for sending messages.
- Utilize [FILTER](https://github.com/vacp2p/rfc-index/blob/7b443c1aab627894e3f22f5adfbb93f4c4eac4f6/waku/standards/core/12/filter.md) for receiving messages.
- Employ [PEER-EXCHANGE](https://github.com/vacp2p/rfc-index/blob/f08de108457eed828dadbd36339433c586701267/waku/standards/core/34/peer-exchange.md#abstract) to discover peers.
- Utilize [STORE](../standards/core/store.md) to obtain message acknowledgements, as described in the Message Storage API section.
If the node is configured in `relay` mode, it MUST:
- Deploy the [RELAY](https://github.com/vacp2p/rfc-index/blob/0277fd0c4dbd907dfb2f0c28b6cde94a335e1fae/waku/standards/core/11/relay.md) protocol.
- Host endpoints for [LIGHTPUSH](../standards/core/lightpush.md) and [FILTER](https://github.com/vacp2p/rfc-index/blob/7b443c1aab627894e3f22f5adfbb93f4c4eac4f6/waku/standards/core/12/filter.md).
- Serve the [PEER-EXCHANGE](https://github.com/vacp2p/rfc-index/blob/f08de108457eed828dadbd36339433c586701267/waku/standards/core/34/peer-exchange.md#abstract) protocol.
It signifies which cluster a node MUST be operating at as per [RELAY-SHARDING](https://github.com/waku-org/specs/blob/186ce335667bdfdb6b2ce69ad7b2a3a3791b1ba6/standards/core/relay-sharding.md).
##### `shards`
This property MUST be provided.
An array of shard under a specified cluster that node MUST operate at as per [RELAY-SHARDING](https://github.com/waku-org/specs/blob/186ce335667bdfdb6b2ce69ad7b2a3a3791b1ba6/standards/core/relay-sharding.md).
This is an optional property that MUST be a positive integer.
If not provided, it defaults to 8.
This property is used to automatically map a provided `contentTopic` to the appropriate `shards` under the specified `clusterId`.
For further details, refer to the [RELAY-SHARDING](https://github.com/waku-org/specs/blob/master/standards/core/relay-sharding.md#content-topics-format-for-autosharding) specification.
A list of `Multiaddr` addresses to remote peers that MUST be used for retrieving past messages or performing infrequent queries using the [STORE](https://github.com/vacp2p/rfc-index/blob/8ee2a6d6b232838d83374c35e2413f84436ecf64/waku/standards/core/13/store.md) protocol.
- a [LIGHTPUSH](../standards/core/lightpush.md) endpoint for broadcasting data;
- a [FILTER](https://github.com/vacp2p/rfc-index/blob/7b443c1aab627894e3f22f5adfbb93f4c4eac4f6/waku/standards/core/12/filter.md) endpoint for receiving circulating data.
- If set to `true`, the `stored` field on `MessageRecord` MUST be populated, and implementations MUST employ store‑based reliability as specified in [P2P‑RELIABILITY](./p2p‑reliability.md).
- If set to `false`, the `stored` field on `MessageRecord` MUST NOT be populated.
- If set to `true`, the node MUST initiate message‑reception detection as specified in [P2P‑RELIABILITY](./p2p‑reliability.md) and populate the `received` field on `MessageRecord`.
- If set to `false`, the `received` field MUST NOT be populated, unless the `Subscribe API` is invoked.
It includes an array of `contentTopics` that the node MUST start monitoring in the background upon initialization,
as defined in the [TOPICS](https://github.com/vacp2p/rfc-index/blob/8ee2a6d6b232838d83374c35e2413f84436ecf64/waku/informational/23/topics.md#content-topic-format) specification.
#### Programmatic API / REST API
No methods or `REST` endpoints are provided for initial configuration.
Instead, the initial configuration MUST be supplied at node creation time according to the guidelines of the chosen implementation.
### Send
The `Send API` is responsible for broadcasting messages across the network using the configured protocol.
The node SHOULD select the appropriate protocol based on its configuration and the protocols that are mounted:
- If the initial configuration specifies mode: `edge`, then [LIGHTPUSH](../standards/core/lightpush.md) MUST be used to send messages.
- If the initial configuration specifies mode: `relay`, then [RELAY](https://github.com/vacp2p/rfc-index/blob/0277fd0c4dbd907dfb2f0c28b6cde94a335e1fae/waku/standards/core/11/relay.md) MUST be used to send messages.
public send(encoder: Encoder, message: Message): RequestID;
public cancelRequest(requestId: RequestID): void;
public getPendingRequests(): RequestID[];
};
```
##### `Encoder`
The `Encoder` object encapsulates the logic for message handling.
It MUST ensure that messages are encoded into the appropriate format for transmission.
Additionally, it MUST provide information regarding the `pubsubTopic` and `contentTopic` to which messages SHOULD be sent.
The specific types of encoders, their extended functionalities, and the mechanisms for their instantiation are considered out of scope for this document.
A `Message` object MUST conform to the [MESSAGE](https://github.com/vacp2p/rfc-index/blob/8ee2a6d6b232838d83374c35e2413f84436ecf64/waku/standards/core/14/message.md) specification.
When invoked, the method schedules the message to be sent via [LIGHTPUSH](../standards/core/lightpush.md) or [RELAY](https://github.com/vacp2p/rfc-index/blob/0277fd0c4dbd907dfb2f0c28b6cde94a335e1fae/waku/standards/core/11/relay.md) based on the node’s configuration.
The method MUST throw an error if the `pubsubTopic` provided by the `Encoder` is not supported by the underlying node.
The method MUST return the associated `RequestID` for the scheduled send attempt.
If the send operation fails, it MAY be retried from the `Message Storage API` using the `RequestID`.
Additionally, send operation can be monitored by subscribing to `message:sent` or `message:error` events described in `Event Source API` below.
##### `cancelRequest`
Cancels a scheduled send attempt associated with a given `RequestID`.
A call to this method MUST be ignored if the request has already been fulfilled (i.e., if it has succeeded, failed, or been canceled previously) or if the provided `RequestID` is invalid.
##### `getPendingRequests`
Returns an array of unique `RequestID` values corresponding to send operations that are still pending.
A request is considered pending if it has not yet succeeded,
and it may be actively retrying or scheduled for sending but has not yet been served.
No duplicate `RequestID` values MUST appear in the returned array.
The `Subscribe API` SHOULD be used to initiate a subscription over [FILTER](https://github.com/vacp2p/rfc-index/blob/7b443c1aab627894e3f22f5adfbb93f4c4eac4f6/waku/standards/core/12/filter.md) or [RELAY](https://github.com/vacp2p/rfc-index/blob/0277fd0c4dbd907dfb2f0c28b6cde94a335e1fae/waku/standards/core/11/relay.md) for continuous message retrieval.
Upon invocation of the Subscribe API, implementations MUST:
- Establish a subscription via either the [FILTER](https://github.com/vacp2p/rfc-index/blob/7b443c1aab627894e3f22f5adfbb93f4c4eac4f6/waku/standards/core/12/filter.md) protocol or the [RELAY](https://github.com/vacp2p/rfc-index/blob/0277fd0c4dbd907dfb2f0c28b6cde94a335e1fae/waku/standards/core/11/relay.md) protocol, based on the node’s configured reception method.
- Ensure active subscriptions comply with the recommendations defined in [P2P‑RELIABILITY](./p2p‑reliability.md).
The `Message Storage API` SHOULD be used to retrieve information about messages that have been sent,
received, or stored.
Message storage is populated by:
- Messages sent by the underlying node via the `Send API`.
- Messages received through an active subscription initiated by the `Subscribe API`.
- Messages fetched using the `History API`.
Messages can be identified by:
- The `message hash` as described in the [MESSAGE](https://github.com/vacp2p/rfc-index/blob/8ee2a6d6b232838d83374c35e2413f84436ecf64/waku/standards/core/14/message.md#deterministic-message-hashing) specification.
- The `contentTopic` associated with the message, as defined in the [TOPICS](https://github.com/vacp2p/rfc-index/blob/main/waku/informational/23/topics.md#content-topic-format) specification.
- The `RequestID` described in the `Send API` section.
- The `SubscriptionID` described in the `Subscribe API` section.
These identifiers SHOULD be passed to the appropriate methods described below to retrieve or manage messages.
Depending on the presence of the `storeConfirmation` or `receiveConfirmation` options in the `Initial configuration`, the `Message Storage API` will trigger either the `Subscribe API` or `Acknowledgements` routine.
Once a message is added to the `Message Storage API`, or if any details about it change,
the appropriate events from the `message:*` event family (as described in the `Event Source API` section) MUST be invoked after the message is added or updated in the underlying storage.
Indicates whether a message has been confirmed to be present in the underlying [STORE](../standards/core/store.md) protocol.
This property is populated based on a recurring [STORE](../standards/core/store.md) query described in `Acknowledgements` section or via the `History API`.
Once a message is confirmed as stored, the `stored` property MUST be updated to `true` as a final state.
If an error occurs during reception, the `error` field MUST be populated with implementation-specific details.
##### `received`
Defaults to `false`.
Indicates whether a message was successfully received from the network via `Subscribe API`.
Once a message is received, the `received` property MUST be updated to `true` as a final state.
If an error occurs during reception, the `error` field MUST be populated with implementation-specific details.
##### `requestId`
Defaults to `null`.
An optional property applicable only to messages sent by the underlying node via the `Send API`.
When present, it corresponds to the `RequestID` from the `Send API`, remains constant once set.
##### `message`
This includes, but is not limited to, the following attributes:
-`payload`: MUST contain the message data payload.
-`contentTopic`: MUST specify a string identifier used for content-based filtering.
-`meta`: If present, contains an arbitrary application-specific variable-length byte array (maximum 64 bytes) for supplementary details.
-`version`: If present, contains a version number to distinguish different types of payload encryption; if omitted, it SHOULD be interpreted as version 0.
-`timestamp`: If present, indicates the time the message was generated (in Unix epoch nanoseconds); if omitted, it SHOULD be interpreted as 0.
-`ephemeral`: If present and `true`, the message is considered transient and SHOULD not be persisted; if omitted or `false`, the message is considered non-ephemeral.
For a complete description of the message attributes,
refer to the [MESSAGE](https://github.com/vacp2p/rfc-index/blob/8ee2a6d6b232838d83374c35e2413f84436ecf64/waku/standards/core/14/message.md#message-attributes) specification.
##### `error`
An optional property that, if present, indicates that an error occurred during the processing of the message—whether while sending or upon receiving.
This may include network, protocol, decoding errors, or other implementation-specific issues.
Once set, the error persists; however, if a message that initially encountered an error (e.g., associated with a `RequestID`) is later successfully transmitted, the error information MUST be cleared.
#### Methods
##### `getByRequestId`
Retrieves the `MessageRecord` corresponding to the specified `RequestID` associated with a send request for a particular message.
If the provided `RequestID` is invalid or no associated `MessageRecord` exists,
the method MUST return nothing.
##### `getByHash`
Retrieves the `MessageRecord` corresponding to the provided `message hash`.
The hash is computed deterministically based on the message content,
as described in the [MESSAGE](https://github.com/vacp2p/rfc-index/blob/8ee2a6d6b232838d83374c35e2413f84436ecf64/waku/standards/core/14/message.md#deterministic-message-hashing) specification.
If the provided hash is invalid or no associated `MessageRecord` exists,
the method MUST return nothing.
##### `getByContentTopic`
Retrieves an array of `MessageRecord` objects corresponding to messages that were circulated under the specified `contentTopic`.
The method accepts two optional parameters for pagination:
-`skip`: A non-negative integer specifying the number of initial matching records to bypass. If `skip` exceeds the total number of matching records, the method MUST return an empty array.
-`take`: A non-negative integer specifying the maximum number of records to return. If `take` is 0, the method MUST return an empty array. If `take` is greater than the number of available records, all remaining matching records are returned.
If both `skip``and` take are omitted, the method MUST return all matching records.
If no records match the specified `contentTopic`, an empty array MUST be returned.
##### `getBySubscriptionId`
Retrieves an array of `MessageRecord` objects corresponding to messages received under the specified `SubscriptionID` (as defined in the `Subscribe API` section).
The method accepts two optional parameters for pagination:
-`skip`: A non-negative integer specifying the number of initial matching records to bypass. If `skip` exceeds the total number of matching records, the method MUST return an empty array.
-`take`: A non-negative integer specifying the maximum number of records to return. If `take` is 0, the method MUST return an empty array. If `take` is greater than the number of available records, all remaining matching records are returned.
If both `skip` and `take` are omitted, the method MUST return all matching records.
If no records match the specified `SubscriptionID`, an empty array MUST be returned.
#### REST API
##### By `RequestID`
Request:
```http
GET /message?requestId=xyz789 HTTP/1.1
Accept: application/json
```
Response:
```http
HTTP/1.1 200 OK
Content-Type: application/json
{
"sending": true,
"sent": false,
"stored": false,
"received": false,
"requestId": "xyz789",
"message": {
"payload": "U29tZSBvdGhlciBkYXRh",
"contentTopic": "/example/another-topic"
}
}
```
Error for `404`:
```http
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": "Message with requestId 'xyz789' not found"
}
```
##### By hash
Request:
```http
GET /message?hash=abc123 HTTP/1.1
Accept: application/json
```
Response:
```http
HTTP/1.1 200 OK
Content-Type: application/json
{
"sending": false,
"sent": false,
"stored": true,
"received": false,
"message": {
"payload": "SGVsbG8gd29ybGQ=",
"contentTopic": "/example/topic"
}
}
```
Error for `404`:
```http
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": "Message with hash 'abc123' not found"
}
```
##### By `contentTopic`
Request:
```http
GET /messages?contentTopic=/messaging/2/api/utf8&skip=0&take=10 HTTP/1.1
Accept: application/json
```
Note: If skip and take are omitted, the request URL would be:
```http
GET /messages?contentTopic=/messaging/2/api/utf8 HTTP/1.1
```
Response:
```http
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"sent": false,
"stored": false,
"received": true,
"message": {
"payload": "SW5pdGlhbCBtZXNzYWdl",
"contentTopic": "/messaging/2/api/utf8"
}
}
]
```
Error for `404`:
```http
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": "No messages found for contentTopic '/messaging/2/api/utf8'"
}
```
##### By `subscriptionId`
Request:
```http
GET /messages?subscriptionId=1692854c-cbde-4afe-901f-1c86ecbd9ea1&skip=0&take=10 HTTP/1.1
Accept: application/json
```
Note: When omitting pagination parameters, the URL would be:
```http
GET /messages?subscriptionId=1692854c-cbde-4afe-901f-1c86ecbd9ea1 HTTP/1.1
```
Response:
```http
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"sent": false,
"stored": false,
"received": true,
"message": {
"payload": "SW5pdGlhbCBtZXNzYWdl",
"contentTopic": "/messaging/2/api/utf8"
}
}
]
```
Error for `404`:
```http
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": "No messages found for subscriptionId '1692854c-cbde-4afe-901f-1c86ecbd9ea1'"
}
```
### Health Indicator
The `Health Indicator API` SHOULD be used to monitor the operational health of a node operating under the `Messaging API`.
The criteria for determining a node’s health state MAY vary depending on the protocols in use and the node’s configuration.
Detailed criteria for each health state are provided in the subsequent sections.
For the purposes of this specification, three health states are defined:
-`unhealthy`: Indicates that the node has lost connectivity for message reception, sending, or both, and as a result, it cannot reliably process or transmit messages.
-`minimally healthy`: Indicates that the node meets the minimum operational requirements, although performance or reliability may be impacted.
-`healthy`: Indicates that the node is operating optimally, with full support for message processing and transmission.
Furthermore, any change in the node’s health state MUST trigger a `health:change` event via the `Event Source API` immediately after the state transition occurs.
Refer to `Event Source API` for more details.
#### Health states
##### `unhealthy`
Indicates that the node’s connectivity is insufficient for reliable operation.
In this state:
- No connections to service nodes are available, regardless of protocol.
- No peers are present in the [RELAY](https://github.com/vacp2p/rfc-index/blob/0277fd0c4dbd907dfb2f0c28b6cde94a335e1fae/waku/standards/core/11/relay.md) mesh.
- The node has at least one connection to a service node implementing [FILTER](https://github.com/vacp2p/rfc-index/blob/7b443c1aab627894e3f22f5adfbb93f4c4eac4f6/waku/standards/core/12/filter.md) and one connection to a service node implementing [LIGHTPUSH](../standards/core/lightpush.md).
- The [RELAY](https://github.com/vacp2p/rfc-index/blob/0277fd0c4dbd907dfb2f0c28b6cde94a335e1fae/waku/standards/core/11/relay.md) mesh includes connections to at least four other peers.
- The node has at least two connections to service nodes implementing [FILTER](https://github.com/vacp2p/rfc-index/blob/7b443c1aab627894e3f22f5adfbb93f4c4eac4f6/waku/standards/core/12/filter.md) and at least two connections to service nodes implementing [LIGHTPUSH](../standards/core/lightpush.md).
- The [RELAY](https://github.com/vacp2p/rfc-index/blob/0277fd0c4dbd907dfb2f0c28b6cde94a335e1fae/waku/standards/core/11/relay.md) mesh includes connections to at least six other peers.
For the `REST API`, long polling over the `Message Store API` SHOULD be used.
##### `message:error`
This event MUST be dispatched when an error occurs during the processing of a message whether while sending or receiving.
In such cases, the `error` property of the corresponding `MessageRecord` is populated with implementation-specific error information.
The event payload is the `MessageRecord` containing the error details.
Once a previously errored message is successfully transmitted, the error information MUST be cleared and an updated event (such as `message:sent` or `message:change`) should be dispatched.