# HTTP read task

> Poll a web API and record values from its JSON responses in channels.

An HTTP read task polls a web API at a fixed rate and records values from each JSON response in channels. Before you start, [connect an HTTP server](https://docs.synnaxlabs.com/reference/hardware/http/connect-server).

## Endpoints and fields

An endpoint is one request. A field is one value in its JSON response, found by a [JSON pointer](https://datatracker.ietf.org/doc/html/rfc6901) such as `/temperature`, and recorded in one channel.

* **Numbers** -> recorded as they are.
* **Booleans** -> recorded as 1 and 0.
* **Strings** -> converted with the **Enum mapping**, else read as a number. A string channel records the text.

The **Source** of an endpoint sets its timestamps:

* **Poll time** -> the time halfway through the request.
* **Response value** -> a time in the response, at a **Pointer**, in a **Format**: ISO 8601, or Unix time in seconds, milliseconds, microseconds, or nanoseconds.

## Create an HTTP read task

[Enterprise](https://docs.synnaxlabs.com/reference/get-started/editions "Needs Synnax Enterprise")

**Console**

1. In the devices toolbar, right-click the server and select **Create read task**.
2. Set **Rate**, the number of requests per second to each endpoint.
3. Click **Add endpoint**, then set **Method** and **Path**, such as `/api/data`.
4. Click **Add field** on the endpoint, then set **Pointer** and **Data type**.
5. Click (**Start**).

The Console creates a channel for each field and an index channel for each endpoint, named from the server, path, and pointer. To choose a name, set **Channel** before you start.

[](https://synnax.nyc3.cdn.digitaloceanspaces.com/docs/hardware/http/read-task/cb0f7b2f5524-dark.mp4#t=0.001)

**Python**

Python does not create channels. Create one index channel for each endpoint first.

```python
import synnax as sy
from synnax import http

server = client.devices.retrieve(name="Weather station")
time = client.channels.create(
    name="weather_time", is_index=True, data_type=sy.DataType.TIMESTAMP
)
temperature = client.channels.create(
    name="weather_temperature", index=time.key, data_type=sy.DataType.FLOAT64
)

task = http.ReadTask(
    name="Weather station read",
    device=server.key,
    rate=1,
    endpoints=[
        http.ReadEndpoint(
            method="GET",
            path="/api/data",
            fields=[
                http.ReadField(pointer="/temperature", channel=temperature.key)
            ],
        )
    ],
)
client.tasks.configure(task)
task.start()
```

**TypeScript**

TypeScript does not create channels. Create one index channel for each endpoint first.

```typescript
import { http } from "@synnaxlabs/client";

const [server] = await client.devices.retrieve({
  where: { name: { eq: "Weather station" } },
});
const time = await client.channels.create({
  name: "weather_time",
  isIndex: true,
  dataType: "timestamp",
});
const temperature = await client.channels.create({
  name: "weather_temperature",
  index: time.key,
  dataType: "float64",
});

const task = await client.tasks.create({
  name: "Weather station read",
  rack: server.rack,
  type: "http_read",
  config: http.readConfigZ.parse({
    device: server.key,
    rate: 1,
    endpoints: [
      {
        method: "GET",
        path: "/api/data",
        fields: [{ pointer: "/temperature", channel: temperature.key }],
      },
    ],
  }),
});
await task.start();
```

## Task options

| Console label | Python field           | Default | Notes                                                                                |
| ------------- | ---------------------- | ------- | ------------------------------------------------------------------------------------ |
| Rate          | `rate`                 | 1 Hz    | Requests per second to each endpoint. One sample for each field.                     |
| Data saving   | `data_saving_disabled` | On      | See [data saving](https://docs.synnaxlabs.com/reference/hardware/tasks#data-saving). |
| Auto start    | `auto_start`           | Off     | Starts the task each time the Driver starts.                                         |

An invalid field skips every field that shares its endpoint and index channel. Turn on **NaN fill** (`nan_fill_enabled`) to write `NaN` for an invalid float field instead. It still sends a warning. Invalid non-float fields always skip the group.

The task has no [stream rate](https://docs.synnaxlabs.com/reference/hardware/tasks#read-tasks). Each response goes to the Core at once.

## Endpoint and field reference

Each setting shows its Console label, then its Python field. An endpoint has these settings:

| Setting                         | Default | Notes                                                           |
| ------------------------------- | ------- | --------------------------------------------------------------- |
| Method `method`                 | `GET`   | `GET` or `POST` in the Console. Code accepts any method.        |
| Path `path`                     |         | Added to the base address of the server.                        |
| Query parameters `query_params` | None    | A list of `{parameter, value}`.                                 |
| Headers `headers`               | None    | A list of `{name, value}`.                                      |
| Body `body`                     | Empty   | Sent only with methods that take a body, as `application/json`. |

A field has these settings:

| Setting                    | Default   | Notes                                           |
| -------------------------- | --------- | ----------------------------------------------- |
| Pointer `pointer`          |           | The JSON pointer to the value.                  |
| Data type `data_type`      | `float64` | Used only when the Console creates the channel. |
| Channel `channel`          |           | The channel that records the value.             |
| Enum mapping `enum_values` | None      | Maps text labels in the response to numbers.    |
| Optional `optional`        | Off       | A missing value is normal for this field.       |
| Fill value `fill_value`    | None      | Written when an optional value is missing.      |

Turn on **Optional** for a value that can be missing as a normal state of the device, such as a sensor that is off. A value is missing when its pointer is absent, or when it is `null` or an empty string. On a string channel, an empty string is a real value.

The task then writes the **Fill value** with no warning, so the other fields on its index channel keep writing. With no fill value, it writes `NaN`, so a non-float channel needs one. An index channel cannot be optional.

A wrong pointer on an optional field also sends no warning. Other invalid values still warn. If a request fails, the task skips the field, so an outage does not look like a real reading.

## Troubleshooting

* [index channel ... is referenced by fields on different endpoints](https://docs.synnaxlabs.com/reference/hardware/http/read-task#index-channel-is-referenced-by-fields-on-different-endpoints)

  * Cause

    Two endpoints record into channels that share one index channel.

  * Fix

    Give each endpoint its own index channel.

* [Field ... not found in response from ...](https://docs.synnaxlabs.com/reference/hardware/http/read-task#field-not-found-in-response-from)

  * Cause

    The response has no value at the pointer.

  * Fix

    Check the pointer against a response from the server. Pointers start with `/` and are case sensitive.

* [Falling behind poll rate](https://docs.synnaxlabs.com/reference/hardware/http/read-task#falling-behind-poll-rate)

  * Cause

    The requests take longer than one period.

  * Fix

    Lower **Rate**, or increase **Concurrent requests** on the [server](https://docs.synnaxlabs.com/reference/hardware/http/connect-server#connection-options).

* [The task stopped while the server was down.](https://docs.synnaxlabs.com/reference/hardware/http/read-task#the-task-stopped-while-the-server-was-down)

  * Cause

    The task tries again for a long time, then stops.

  * Fix

    Start the task again when the server is back.

For other problems, see [Troubleshoot hardware](https://docs.synnaxlabs.com/reference/hardware/troubleshooting).
