> Documentation index: https://nao-rs.lukaloehr.com/llms.txt, a list of every page in this documentation.

# Control

> REST API: Control leases. Generated from the OpenAPI document.

## Who controls the robot

`GET /v1/control`

`none`, a `brain` on the MessagePack API, or a REST `lease`. Send your `Nao-Lease` header to learn whether it is yours.

**Token:** required · **Lease:** not needed

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | Who controls the robot | [ControlStatus](https://nao-rs.lukaloehr.com/reference/rest-api/schemas.md#controlstatus) |
| 401 | Missing or wrong token | [ErrorBody](https://nao-rs.lukaloehr.com/reference/rest-api/schemas.md#errorbody) |

```bash
curl -H "Authorization: Bearer $TOKEN" http://$ROBOT:7702/v1/control
```

## Take control

`POST /v1/control`

Returns a lease id for the `Nao-Lease` header of every command. Keep it with a heartbeat at least every 100 ms; the robot stands after 0.5 s of silence, sits after 3 s, and the lease ends after 10 s. The robot starts with no motion commanded. Fails while a brain is connected.

**Token:** required · **Lease:** not needed

**Request body** (`application/json`)

[AcquireRequest](https://nao-rs.lukaloehr.com/reference/rest-api/schemas.md#acquirerequest)

| Field | Type | Required | Meaning |
| --- | --- | --- | --- |
| `client` | string | yes | Who is asking (shown in status and logs), 1 to 64 printable characters. (example `joystick-app`) |
| `takeover` | boolean | no | Replace another client's lease. Never replaces a connected brain. |

```json
{"client":"joystick-app"}
```

| Status | Meaning | Body |
| --- | --- | --- |
| 201 | You control the robot now; it starts with no motion | [LeaseGrant](https://nao-rs.lukaloehr.com/reference/rest-api/schemas.md#leasegrant) |
| 409 | A brain is connected (`brain_connected`) or another client holds the lease (`lease_held`) | [ErrorBody](https://nao-rs.lukaloehr.com/reference/rest-api/schemas.md#errorbody) |
| 422 | Invalid input | [ErrorBody](https://nao-rs.lukaloehr.com/reference/rest-api/schemas.md#errorbody) |

```bash
curl -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"client": "my-script"}' http://$ROBOT:7702/v1/control
```

## Give control back

`DELETE /v1/control`

The robot then behaves as when a brain disconnects: it stands, then sits.

**Token:** required · **Lease:** required (`Nao-Lease` header)

| Status | Meaning | Body |
| --- | --- | --- |
| 204 | Released; the robot stands, then sits, as when a brain disconnects |  |
| 409 | Not the active lease | [ErrorBody](https://nao-rs.lukaloehr.com/reference/rest-api/schemas.md#errorbody) |
| 428 | No `Nao-Lease` header | [ErrorBody](https://nao-rs.lukaloehr.com/reference/rest-api/schemas.md#errorbody) |

```bash
curl -X DELETE -H "Authorization: Bearer $TOKEN" -H "Nao-Lease: $LEASE" http://$ROBOT:7702/v1/control
```

## Keep control

`POST /v1/control/heartbeat`

Any command counts as a heartbeat too.

**Token:** required · **Lease:** required (`Nao-Lease` header)

| Status | Meaning | Body |
| --- | --- | --- |
| 204 | Still in control |  |
| 409 | Not the active lease | [ErrorBody](https://nao-rs.lukaloehr.com/reference/rest-api/schemas.md#errorbody) |
| 428 | No `Nao-Lease` header | [ErrorBody](https://nao-rs.lukaloehr.com/reference/rest-api/schemas.md#errorbody) |

```bash
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Nao-Lease: $LEASE" http://$ROBOT:7702/v1/control/heartbeat
```

## Control over a WebSocket

`GET /v1/control/ws`

Upgrade to a WebSocket (browsers pass the token as `?access_token=`). Send `hello` first; the
socket then holds the lease until it closes. Messages are `WsClientMessage` (client to robot)
and `WsServerMessage` (robot to client) as JSON text. Send something at least every 100 ms:
the robot stands after 0.5 s of silence and sits after 3 s, as with any controller. The messages are on [WsClientMessage](https://nao-rs.lukaloehr.com/reference/rest-api/schemas.md#wsclientmessage) and [WsServerMessage](https://nao-rs.lukaloehr.com/reference/rest-api/schemas.md#wsservermessage).

**Token:** required · **Lease:** not needed

| Status | Meaning | Body |
| --- | --- | --- |
| 101 | Switching to the WebSocket protocol |  |
| 401 | Missing or wrong token | [ErrorBody](https://nao-rs.lukaloehr.com/reference/rest-api/schemas.md#errorbody) |
| 503 | Too many streams open | [ErrorBody](https://nao-rs.lukaloehr.com/reference/rest-api/schemas.md#errorbody) |

```bash
# With websocat (https://github.com/vi/websocat); type the three lines after connecting.
websocat "ws://$ROBOT:7702/v1/control/ws?access_token=$TOKEN"
{"type": "hello", "client": "pad", "id": 1}
{"type": "leds", "group": "eyes", "setting": {"color": "#0050ff"}, "id": 2}
{"type": "volume", "volume": {"percent": 40}, "id": 3}
```

## Related topics

- [REST API](https://nao-rs.lukaloehr.com/reference/rest-api.md)
- [System](https://nao-rs.lukaloehr.com/reference/rest-api/system.md)
- [Robot](https://nao-rs.lukaloehr.com/reference/rest-api/robot.md)
- [State](https://nao-rs.lukaloehr.com/reference/rest-api/state.md)
- [Events](https://nao-rs.lukaloehr.com/reference/rest-api/events.md)
- [Safety](https://nao-rs.lukaloehr.com/reference/rest-api/safety.md)
- [LEDs](https://nao-rs.lukaloehr.com/reference/rest-api/leds.md)
- [Audio](https://nao-rs.lukaloehr.com/reference/rest-api/audio.md)
- [Cameras](https://nao-rs.lukaloehr.com/reference/rest-api/cameras.md)
- [Power](https://nao-rs.lukaloehr.com/reference/rest-api/power.md)
- [Motion](https://nao-rs.lukaloehr.com/reference/rest-api/motion.md)
- [Schemas](https://nao-rs.lukaloehr.com/reference/rest-api/schemas.md)
- Previous: [Safety](https://nao-rs.lukaloehr.com/reference/rest-api/safety.md)
- Next: [LEDs](https://nao-rs.lukaloehr.com/reference/rest-api/leds.md)
