# API & WebSocket Guide

Domains

<table><thead><tr><th width="221">Description</th><th width="270">Testnet URL</th><th>Mainnet URL</th></tr></thead><tbody><tr><td>REST Endpoint to query specific reports</td><td><a href="http://live-api-test.apro.com">https://live-api-test.apro.com</a></td><td><a href="http://live-api.apro.com">https://live-api.apro.com</a></td></tr></tbody></table>

### Authentication

**Headers**

All routes require the following two headers for user authentication:

<table><thead><tr><th width="177">Header</th><th>Description</th></tr></thead><tbody><tr><td><strong>Authorization</strong></td><td>The user’s unique identifier, provided as a UUID (Universally Unique IDentifier).</td></tr><tr><td><strong>X-Authorization-Timestamp</strong></td><td>The current timestamp, with precision up to milliseconds. The timestamp must closely synchronize with the server time, allowing a maximum discrepancy of 5 seconds (by default).</td></tr></tbody></table>

### API endpoints

1. #### Return a single report at a given timestamp

**Endpoint**

> /api/v1/reports

<table><thead><tr><th width="170">Type</th><th width="199">Description</th><th>Parameter(s)</th></tr></thead><tbody><tr><td>HTTP GET</td><td>Returns a single report for a given timestamp.</td><td><ul><li><strong><code>feedID</code></strong>: A Data Streams feed ID.</li><li><strong><code>timestamp</code></strong>: The Unix timestamp for the report.</li></ul></td></tr></tbody></table>

**Sample request**

> GET /api/v1/reports?feedID=\<feedID>\&timestamp=\<timestamp>

**Sample response**

```json
{
    "report": {
        "feedID": "Hex encoded feedId.",
        "validFromTimestamp": "Report's earliest applicable timestamp (in seconds).",
        "observationsTimestamp": "Report's latest applicable timestamp (in seconds).",
        "fullReport": "A blob containing the report context and body. Encode the fee token into the payload before passing it to the contract for verification.",
        "askPrice": "Ask price.",
        "bidPrice": "Bid price.",
        "midPrice": "Mid price."
    }
}
```

<figure><img src="/files/5BcWXOaMsyEu4U53PzGY" alt=""><figcaption></figcaption></figure>

2. #### Return a single report with the latest timestamp

**Endpoint**

> /api/v1/reports/latest

| Type     | Parameter(s)                          |
| -------- | ------------------------------------- |
| HTTP GET | **`feedID`**: A Data Streams feed ID. |

**Sample request**

> GET /api/v1/reports/latest?feedID=\<feedID>

**Sample response**

```json
{
    "report": {
        "feedID": "Hex encoded feedId.",
        "validFromTimestamp": "Report's earliest applicable timestamp (in seconds).",
        "observationsTimestamp": "Report's latest applicable timestamp (in seconds).",
        "fullReport": "A blob containing the report context and body. Encode the fee token into the payload before passing it to the contract for verification.",
        "askPrice": "Ask price.",
        "bidPrice": "Bid price.",
        "midPrice": "Mid price."
    }
}
```

<figure><img src="/files/oswaMNFutDX7wyH5BLvT" alt=""><figcaption></figcaption></figure>

3. #### Return a report for multiple FeedIDs at a given timestamp

**Endpoint**

> /api/v1/reports/bulk

<table><thead><tr><th width="139">Type</th><th width="180">Description</th><th>arameter(s)</th></tr></thead><tbody><tr><td>HTTP GET</td><td>Return a report for multiple FeedIDs at a given timestamp.</td><td><ul><li><strong><code>feedIDs</code></strong>: A comma-separated list of Data Streams feed IDs.</li><li><strong><code>timestamp</code></strong>: The Unix timestamp for the reports or the string 'latest' for getting the latest reports.</li></ul></td></tr></tbody></table>

**Sample request**

> GET /api/v1/reports/bulk?feedIDs=\<FeedID1>,\<FeedID2>,...\&timestamp=\<timestamp>
>
> GET /api/v1/reports/bulk?feedIDs=\<FeedID1>,\<FeedID2>,...\&timestamp=latest

**Sample response**

```json
{
    "reports": [
        {
            "feedID": "Hex encoded feedId.",
            "validFromTimestamp": "Report's earliest applicable timestamp (in seconds).",
            "observationsTimestamp": "Report's latest applicable timestamp (in seconds).",
            "fullReport": "A blob containing the report context and body. Encode the fee token into the payload before passing it to the contract for verification.",
            "askPrice": "Ask price.",
            "bidPrice": "Bid price.",
            "midPrice": "Mid price."
        },
      //...
    ]
}
```

<figure><img src="/files/3f7oG2tzNZAvzOnO0gcz" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/RJUtOYnGoHYRNwWbCHok" alt=""><figcaption></figcaption></figure>

4. #### Return multiple sequential reports for a single FeedID, starting at a given timestamp

**Endpoint**

> /api/v1/reports/page

<table><thead><tr><th width="143">Type</th><th width="213">Description</th><th>Parameter(s)</th></tr></thead><tbody><tr><td>HTTP GET</td><td>Return multiple sequential reports for a single FeedID, starting at a given timestamp.</td><td><ul><li><strong><code>feedID</code></strong>: A Data Streams feed ID.</li><li><strong><code>startTimestamp</code></strong>: The Unix timestamp for the first report.</li><li><strong><code>limit</code></strong> (optional): The number of reports to return.</li></ul></td></tr></tbody></table>

**Sample request**

> GET /api/v1/reports/page?feedID=\<FeedID>\&startTimestamp=\<StartTimestamp>\&limit=\<Limit>

**Sample response**

```json
{
    "reports": [
        {
            "feedID": "Hex encoded feedId.",
            "validFromTimestamp": "Report's earliest applicable timestamp (in seconds).",
            "observationsTimestamp": "Report's latest applicable timestamp (in seconds).",
            "fullReport": "A blob containing the report context and body. Encode the fee token into the payload before passing it to the contract for verification.",
            "askPrice": "Ask price.",
            "bidPrice": "Bid price.",
            "midPrice": "Mid price."
        },
      //...
    ]
}
```

<figure><img src="/files/rWx2smJdwpsm23cqCCBS" alt=""><figcaption></figcaption></figure>

5. #### WebSocket Connection

Establish a streaming WebSocket connection that sends reports for the given feedID(s) after they are verified.

**Endpoint**

> /api/v1/ws

<table><thead><tr><th width="261">Type</th><th>Parameter(s)</th></tr></thead><tbody><tr><td>WebSocket</td><td><strong><code>feedIDs</code></strong>: A comma-separated list of Data Streams feed IDs.</td></tr></tbody></table>

**Sample request**

> GET /api/v1/ws?feedIDs=\<feedID1>,\<feedID2>,...

**Sample response**

```json
{
  "report": {
    "feedID": "hex encoded feedId",
    "fullReport": "a blob containing the report context + body, can be passed unmodified to the contract for verification"
  }
}
```

<figure><img src="/files/7blS25A44QNNaVxx9SAX" alt=""><figcaption></figcaption></figure>

### Error response codes

<table><thead><tr><th width="215">Status Code</th><th>Description</th></tr></thead><tbody><tr><td>400 Bad Request</td><td><p>This error is triggered when:</p><ul><li>There is any missing/malformed query argument.</li><li>Required headers are missing or provided with incorrect values.</li></ul></td></tr><tr><td>401 Unauthorized User</td><td><p>This error is triggered when:</p><ul><li>Authentication fails, typically because the HMAC signature provided by the client doesn't match the one expected by the server.</li><li>A user requests access to a feed without the appropriate permission or that does not exist.</li></ul></td></tr><tr><td>500 Internal Server</td><td>Indicates an unexpected condition encountered by the server, preventing it from fulfilling the request. This error typically points to issues on the server side.</td></tr><tr><td>206 Missing data (<strong><code>/bulk</code></strong> endpoint only)</td><td>Indicates that at least one feed ID data is missing from the report. E.g., you requested a report for feed IDs <strong><code>&#x3C;feedID1></code></strong>, <strong><code>&#x3C;feedID2></code></strong>, and <strong><code>&#x3C;feedID3></code></strong> at a given timestamp. If data for <strong><code>&#x3C;feedID2></code></strong> is missing from the report (not available yet at the specified timestamp), you get <strong><code>[&#x3C;feedID1 data>, &#x3C;feedID3 data>]</code></strong> and a 206 response.</td></tr></tbody></table>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.apro.com/en/data-pull-evm-chain/api-and-websocket-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
