---
title: "Upload binary measurements for an AirBeamMini session"
method: POST
path: "/api/v3/fixed_sessions/{uuid}/measurements"
tags: ["AirBeamMini fixed sessions binary flow"]
---

# Upload binary measurements for an AirBeamMini session

`POST /api/v3/fixed_sessions/{uuid}/measurements`

Receives a binary measurement payload from the AirBeamMini. Can be called once per
minute for live uploads or in bulk after connectivity loss — both are handled identically.

## Binary Format

```
Offset     Size  Type        Description
0          2     uint8[2]    Magic bytes: 0xAB 0xBA
2          2     uint16 BE   Measurement count N
--- repeated N times ---
4+i*9      4     uint32 BE   Unix timestamp (seconds since epoch, UTC)
8+i*9      1     uint8       sensor_type_id (returned by session creation endpoint)
9+i*9      4     float32 BE  Sensor value
--- end repeat ---
4+N*9      1     uint8       XOR checksum of all preceding bytes
```

**Resend behaviour:** sending a measurement with an already-stored
`(stream_id, time_with_time_zone)` pair is silently ignored — no duplicate is created.

**Time synchronisation:** an empty body is valid and returns 200 immediately. The AirBeamMini
uses this to read the current server time from the `X-Server-Time` response header
(Unix epoch, UTC) when its clock drifts.

## Error Codes

All error responses share the shape `{ "error_code": "...", "message": "..." }`.

| `error_code` | HTTP | Description |
|---|---|---|
| `unauthorized` | 401 | Missing or invalid `Authorization` token |
| `session_not_found` | 404 | No session with the given UUID exists for this user/token |
| `payload_too_short` | 400 | Payload has fewer bytes than required for even one frame |
| `invalid_magic_bytes` | 400 | First 2 bytes are not `0xAB 0xBA` |
| `empty_measurement_count` | 400 | Frame count field in header is zero |
| `payload_size_mismatch` | 400 | Actual payload size does not match the declared frame count |
| `invalid_checksum` | 400 | XOR checksum of payload does not match the final byte |
| `invalid_epoch` | 400 | A frame's timestamp is zero or implausibly far in the future |
| `invalid_value` | 400 | A frame's sensor value is NaN or Infinity |

## Path parameters

- `uuid` string, required

## Headers

- `Authorization` string, required

## Response `200`

measurements stored (or empty body time-sync)

## Other responses

- `400` — invalid payload or unknown sensor_type_id
- `401` — unauthorized
- `404` — session not found

---

[API](https://skmtc.net/habitatmap/apis/aircasting-api-v3.md) · [All operations](https://skmtc.net/habitatmap/apis/aircasting-api-v3/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/habitatmap/aircasting-api-v3/revisions/340612ace143/schema)
