# Energy & weather

> Read the forecast energy curve and the weather report for a day. Both endpoints return a short text report.

Source: https://reassign.dev/reference/energy-and-weather/

Use these two endpoints to plan a day around the energy of the user and around the weather. Each endpoint returns one text report for one day.

The machine-readable spec of all public endpoints: [openapi.json](https://reassign.dev/openapi.json).

> Both endpoints are in Beta. The reports are prose for people and AI assistants. The text can change. Do not parse it.

## The report model

Both endpoints return the same object: `{ "report": "…" }`. The object has no other fields.

- `report` is a short text report for one day. It is never empty.
- The first line is a header. Most of the next lines start with a bullet (`•`). The weather lines for the parts of the day and the special texts do not.
- Each `<time>` is a 24-hour clock time, for example `09:24` or `18:36`. The time format setting of the app does not change it.

* `report` (_string, required_)

### Access

| Item   | Value                                                                                                                   |
| ------ | ----------------------------------------------------------------------------------------------------------------------- |
| Scope  | `events:read` or `events:write`                                                                                         |
| Plan   | A trial or Pro plan                                                                                                     |
| Method | `GET` only                                                                                                              |
| Query  | Only the parameters of the endpoint. An unknown or a repeated query parameter returns `422` with the code `validation`. |

### What energy is

The energy curve is a forecast of the alertness of the user during a day.

- Reassign makes the curve from the logged sleep of the user, and from tracked caffeine.
- Energy check-ins that the user logs make the curve personal. With no check-ins, the curve is a population estimate.
- The curve needs at least one logged night of sleep.
- For a future day, Reassign uses the usual sleep of the user.
- For a past day, Reassign uses the logged sleep. Reassign calculates the energy with a model. It does not measure it.
- When the user has no saved sleep need, Reassign uses 8 hours.

### Where the weather data comes from

- The forecast and the place search come from [Open-Meteo](https://open-meteo.com).
- The forecast covers approximately 16 days ahead and 7 days back. Other days have no hourly data.
- Reassign rounds the coordinates to 0.1° (approximately 11 km).
- The temperature unit is °C or °F. It comes from the weather units setting of the user, or from the time zone.

---

## Read the energy curve (Beta)

**GET** `/api/v1/energy`

> This route is in Beta. The response can change.

Get the forecast energy curve for one day as a text report. The report gives the peaks and the dips to plan around.

- Without `date`, the day is today in the time zone of the account.
- A `date` that is not a real `YYYY-MM-DD` date returns `422` with the code `validation`. The message starts with `` `date`: ``.

### Report lines

| Line                                                                                                 | When                                                                                                                  |
| ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `Energy for <Weekday>, <date>:`                                                                      | Always. It adds ` (today)` for today. For a past day it adds a note that the energy is modeled from the logged sleep. |
| `• Peak: morning ~<time>`, `• Peak: evening ~<time>`, or `• Peaks: morning ~<time>, evening ~<time>` | When the curve has a peak                                                                                             |
| `• Afternoon dip ~<time>`                                                                            | When the curve has a dip                                                                                              |
| `• Morning grogginess until ~<time>`                                                                 | When the curve has grogginess                                                                                         |
| `• Right now (~<time>): <n>/100`, then an optional `: <driver>, <driver>` (a maximum of 2 drivers)   | Today only                                                                                                            |
| `• Peak today ~<n>/100.`                                                                             | Always, when the curve can show                                                                                       |
| `• Personalized from <n> energy check-ins.` or `• Population estimate. …`                            | Always, when the curve can show                                                                                       |
| `• Carrying ~<n>h sleep debt …`                                                                      | When the sleep debt is 1 hour or more                                                                                 |

When the curve cannot show, the report has the header and one of these texts:

- No sleep logged: `No energy curve yet. I haven't seen any logged sleep. …`
- The night before the day is not logged: `The night before this day isn't logged, so I can't draw its curve. …`

### Query parameters

- `date` (_string_): The day; defaults to today.

### Response fields

- `report` (_string, required_)

### Responses

| Status | Codes                 | Meaning                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ------ | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | —                     | Success.                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `401`  | `unauthorized`        | No Bearer token and no session cookie, or the token is invalid, expired, or revoked. The response carries a `WWW-Authenticate` challenge that points at the protected-resource metadata.                                                                                                                                                                                                                                                                                               |
| `403`  | `permission`, `scope` | A token without `events:read` or `events:write` gets `scope` "This token is not authorized to read events (requires events:read or events:write scope)." An account without Reassign Pro access gets `permission` "Reassign needs an active subscription." The 7-day free trial includes Reassign Pro. A cookie session from another site gets `permission` "Cross-origin request."                                                                                                    |
| `422`  | `validation`          | A query parameter is not valid. The message names the first bad field by its path. A repeated or unknown query parameter is also a 422.                                                                                                                                                                                                                                                                                                                                                |
| `429`  | `rate_limited`        | Too many requests. The edge firewall limits each IP to 2000 requests per minute across `/api/v1`; that 429 comes from the edge and can have a body that is not this JSON and no `Retry-After` header. When an edge 429 has no `Retry-After`, retry after 60 seconds. The app also limits each Bearer credential to 600 requests per minute, and some routes limit each user. These limits return this body. This app 429 always has `Retry-After`: retry after that number of seconds. |
| `503`  | `internal`            | A fault on our side. The request is safe to retry.                                                                                                                                                                                                                                                                                                                                                                                                                                     |

**Request** — **GET** `/api/v1/energy`

**cURL**

```bash
curl "https://reassign.app/api/v1/energy" \
  -H "Authorization: Bearer rsk_live_YOUR_TOKEN"
```

**JavaScript**

```js
const res = await fetch("https://reassign.app/api/v1/energy", {
  headers: {
    Authorization: "Bearer rsk_live_YOUR_TOKEN",
  },
});
const data = await res.json();
```

**Response**

```json
{
  "report": "Energy for Thursday, 2026-08-13 (today):\n• Peaks: morning ~09:24, evening ~18:36\n• Afternoon dip ~14:15\n• Morning grogginess until ~08:15\n• Right now (~10:42): 71/100: body clock strong, well rested\n• Peak today ~75/100.\n• Population estimate. Log how your energy feels (a Mood/energy moment) to personalize it."
}
```

---

## Read the weather report (Beta)

**GET** `/api/v1/weather`

> This route is in Beta. The response can change.

Get a short weather report for one day. Use it to plan outdoor blocks.

- Without `date`, the day is today in the time zone of the place, or in the time zone of the account.
- A `date` that is not a real `YYYY-MM-DD` date returns `422` with the code `validation`. The message starts with `` `date`: ``.
- For `location`, send a place name, for example `Paris, France`. Reassign trims it and uses the first match of the place search. A blank `location` returns `422`.
- Without `location`, Reassign uses the saved city of the user. With no saved city, Reassign guesses a city from the time zone.
- With `location`, the forecast date and times are local to that place. The report header adds `date and times in <IANA timezone>`, for example `date and times in Europe/Paris`.

### Report lines

| Line                                                                                                                                       | When                                                                 |
| ------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
| `Weather for <place> on <Weekday>, <date>:`                                                                                                | Always. It adds ` (today)` for today.                                |
| `• <condition>, <low>–<high><unit>`                                                                                                        | When the day has hourly data                                         |
| `• Rain likely <from>–<to> (<n>% peak)`, `• Rain likely at <time> (<n>% peak)` (one wet hour), or `• Dry — no rain expected`               | When the day has hourly data. For snow, the line starts with `Snow`. |
| `• Daylight <sunrise>–<sunset>`                                                                                                            | When the sunrise and the sunset are known                            |
| `• Pressure <low / normal / high>`, then an optional `, falling through the day` or `, rising through the day` (a change of 3 hPa or more) | When the day has 2 or more hours of pressure data                    |
| `  Morning:`, `Afternoon:`, `Evening:`, `Night:`                                                                                           | One line for each part of the day that has data                      |

### Special reports

These reports are a `200` response, not an error.

| Case                                    | Report text                                                                                  |
| --------------------------------------- | -------------------------------------------------------------------------------------------- |
| No hourly data for the day              | The header, then `No hourly forecast available for this day.`                                |
| Reassign cannot find `location`         | `Couldn't find a place named "<location>". …`                                                |
| No saved city, and an unknown time zone | `No city is set for weather, and your timezone isn't recognized. …`                          |
| The city is a guess from the time zone  | The header adds the note `approx. location from your timezone — set your city for accuracy`. |

### Query parameters

- `date` (_string_): The day; defaults to today.
- `location` (_string_): A place name; defaults to the saved city.

### Response fields

- `report` (_string, required_)

### Responses

| Status | Codes                 | Meaning                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ------ | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | —                     | Success.                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `401`  | `unauthorized`        | No Bearer token and no session cookie, or the token is invalid, expired, or revoked. The response carries a `WWW-Authenticate` challenge that points at the protected-resource metadata.                                                                                                                                                                                                                                                                                               |
| `403`  | `permission`, `scope` | A token without `events:read` or `events:write` gets `scope` "This token is not authorized to read events (requires events:read or events:write scope)." An account without Reassign Pro access gets `permission` "Reassign needs an active subscription." The 7-day free trial includes Reassign Pro. A cookie session from another site gets `permission` "Cross-origin request."                                                                                                    |
| `422`  | `validation`          | A query parameter is not valid. The message names the first bad field by its path. A repeated or unknown query parameter is also a 422.                                                                                                                                                                                                                                                                                                                                                |
| `429`  | `rate_limited`        | Too many requests. The edge firewall limits each IP to 2000 requests per minute across `/api/v1`; that 429 comes from the edge and can have a body that is not this JSON and no `Retry-After` header. When an edge 429 has no `Retry-After`, retry after 60 seconds. The app also limits each Bearer credential to 600 requests per minute, and some routes limit each user. These limits return this body. This app 429 always has `Retry-After`: retry after that number of seconds. |
| `503`  | `internal`            | A fault on our side. The request is safe to retry.                                                                                                                                                                                                                                                                                                                                                                                                                                     |

**Request** — **GET** `/api/v1/weather`

**cURL**

```bash
curl "https://reassign.app/api/v1/weather" \
  -H "Authorization: Bearer rsk_live_YOUR_TOKEN"
```

**JavaScript**

```js
const res = await fetch("https://reassign.app/api/v1/weather", {
  headers: {
    Authorization: "Bearer rsk_live_YOUR_TOKEN",
  },
});
const data = await res.json();
```

**Response**

```json
{
  "report": "Weather for Ljubljana on Thursday, 2026-08-13 (today):\n• Clear, 16–25°C\n• Rain likely 15:00–17:00 (70% peak)\n• Daylight 06:06–20:15\n  Morning: 19°C, clear\n  Afternoon: 24°C, rain\n  Evening: 25°C, clear\n  Night: 16°C, clear"
}
```
