# Introduction

Welcome to the Fotokite API documentation!

<figure><img src="https://3669484394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXUDGlNkSLzd9Nbig1oF3%2Fuploads%2FEB2oecp4iYv9Mvw3PYxC%2Fkey-visual.png?alt=media&amp;token=d64ab5d5-6e99-419d-a73f-400dff671bc0" alt=""><figcaption></figcaption></figure>

The Fotokite API is an HTTP API to be used in a local network, with request and response bodies encoded in JSON format. It is designed as a high-level interface, enabling users to both receive data and control the system. It supports the core features available in Fotokite Live (Learn more in [Fotokite Live Walkthrough](https://manual.fotokite.com/fotokite-live-walkthrough)). The API is intended to allow customers and partners to build their own integrations and automations with ease.

The API provides three different ways of retrieving information.

* REST interface - For infrequent information and commanding the system.
* WebSocket interface - For frequently changing information/telemetry.
* RTSP Streams - For the video streams.

## Disclaimer

Developers using the Fotokite API are responsible for ensuring their applications comply with all relevant laws and regulations, including but not limited to local and national aviation authorities (e.g., the FAA or equivalent regulatory bodies). Fotokite assumes no responsibility for any use of its APIs that violates such regulations. The API is provided "as is" without warranties of any kind, either express or implied, including but not limited to warranties of merchantability or fitness for a specific purpose, to the fullest extent permitted by applicable law.


# Getting started

## Get API access

The Fotokite API must be enabled by Fotokite. Please contact us to have your Fotokite system enrolled.

<a href="https://fotokite.com/contact/contact-form/" class="button primary">Contact Fotokite</a>

## Access the API

{% stepper %}
{% step %}
Update the Fotokite system to the latest software version.
{% endstep %}

{% step %}
Choose one of the following network setups and follow the linked instructions:

* **Standalone setup**\
  Connect your client device directly to the Ground Station. \
  Select [Network Integration](/network-integration#standalone-setup)
* **Integrated setup**\
  Connect both the Ground Station and your client device to the same local network. \
  Select [Network Integration](/network-integration#integrated-setup)
  {% endstep %}

{% step %}
Once the network setup is complete, you can access the API.

```bash
# HTTP (Standalone setup)
curl http://192.168.2.100:3128/api/v1/health

# HTTPS (Integrated setup)
curl https://<fotokite-system-name>.sigma.fotokite-system.com/api/v1/health
```

The `/health` endpoint does not require authentication. For all other endpoints, use authenticated requests as described in [#authentication](#authentication "mention").

For simplicity, this guide uses the URL for the Standalone setup. If you are using the Integrated setup, replace the URL accordingly.

If the command hangs, times out, or returns a “no route to host” error, your client device is not correctly connected to the Fotokite system.
{% endstep %}
{% endstepper %}

## Authentication

The authentication mechanism ensures proper security and access control. Most API endpoints are protected and scoped, meaning each request to a protected endpoint must include a valid bearer token. The Fotokite API offers two authentication mechanism:

1. Get a token via Token Management
2. Get a token via API Key

You can find more details in [Authentication and Security](/authentication-and-security)

### Get a token via Token Management

The simplest way to obtain a token is through our Token Management system. This method is recommended if you manage fewer than five systems.

{% stepper %}
{% step %}
Connect a computer with a web browser to the same network as your Fotokite system. We recommend using Wi-Fi.
{% endstep %}

{% step %}
Open the following URL in your browser.

```bash
http://192.168.2.100:3128/api/token_management
```

<figure><img src="https://3669484394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXUDGlNkSLzd9Nbig1oF3%2Fuploads%2F1gRTT2HdSvg0vzPy3Wiw%2Ftoken-management.jpg?alt=media&amp;token=edae2782-3a9c-4142-af80-90c58cf4522c" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Click the Create API token button to create a new token.

* Name: The name will help you organize your tokens. It will also be visible in Fotokite Live whenever your app uses that token to perform any controls.
* Scope: Token scopes determine which endpoint(s) an API token can access.
  * read: Access to all endpoints for retrieving information, except `/control` endpoints.
  * control: Access to `/control` endpoints.
  * experimental: Access to experimental and unstable features.
    {% endstep %}

{% step %}
The token (bearer token) is used to authenticate all subsequent requests to protected endpoints.

```bash
# System information
curl -X GET "http://192.168.2.100:3128/api/v1/system/info" \
--oauth2-bearer <auth_token>
```

{% endstep %}

{% step %}
Tokens can be invalidated via [Authentication](/fotokite-api/authentication#post-v0-auth-token-invalidate). Once a token is invalidated, you must request a new one using Token Management.

Good to know: This token does not expire.
{% endstep %}
{% endstepper %}

## Retrieve system information

Basic information about the system, flight, camera, and other components can be retrieved using the endpoints in the `/info` namespace:

```bash
# System information
curl -X GET "http://192.168.2.100:3128/api/v1/system/info" \
--oauth2-bearer <auth_token>

# Flight information
curl -X GET "http://192.168.2.100:3128/api/v1/flight/info" \
--oauth2-bearer <auth_token>

# Camera information
curl -X GET "http://192.168.2.100:3128/api/v1/camera/info" \
--oauth2-bearer <auth_token>
```

## Control the system

To control the system, you must use the endpoints in the `/control` namespace. It is important to note that these endpoints are part of the Control Handoff mechanism. Control Handoff ensures that only one client can control the system at any given time. Before using any endpoint in the `/control` namespace, the application must first request control.

To keep the API in control, request control has to be sent in regular intervals by the client. Please find more details in [Handoff](/fotokite-api/handoff#post-v0-handoff-control-request).

{% code fullWidth="false" %}

```bash
# Request control
curl -X POST "http://192.168.2.100:3128/api/v1/handoff/control/request" \
  -H "Authorization: Bearer <auth_token>"
  -H "Content-Type: application/json" \
  -d '{"operator_name":"YOUR_OPERATOR_NAME"}'

# Take off
curl -X POST "http://192.168.2.100:3128/api/v1/flight/control/take_off" \
  -H "Authorization: Bearer <auth_token>"

# Set Altitude
curl -X POST "http://192.168.2.100:3128/api/v1/flight/control/set_altitude" \
  -H "Authorization: Bearer <auth_token>" \
  -H "Content-Type: application/json" \
  -d '{"altitude":21}'

# Land
curl -X POST "http://192.168.2.100:3128/api/v1/flight/control/land" \
  -H "Authorization: Bearer <auth_token>"

# Release control
curl -X POST "http://192.168.2.100:3128/api/v1/handoff/control/request" \
  -H "Authorization: Bearer <auth_token>"
```

{% endcode %}

If Fotokite Live is currently in control when the API requests control, an alert will be displayed to the operator. The operator can choose to allow or cancel the request. If the request is canceled, no additional alerts will appear for the next two minutes.

<figure><img src="https://3669484394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXUDGlNkSLzd9Nbig1oF3%2Fuploads%2F07KjHZNBDC7M5T5SuwEL%2Fgetting-started-request-control.png?alt=media&amp;token=b6c23981-5ac4-4915-a9ad-ff809204becc" alt=""><figcaption></figcaption></figure>

Fotokite Live can always take control back from the API by pressing the Take Control button in the bottom-right corner.

<figure><img src="https://3669484394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXUDGlNkSLzd9Nbig1oF3%2Fuploads%2FNTduzZwVvwqy44mUiaF8%2Fgetting-started-control-handoff.png?alt=media&amp;token=abc36d02-7443-48dd-ab7c-5aaef4359da8" alt=""><figcaption><p>In Fotokite Live, control is blocked when the API has control.</p></figcaption></figure>

## Retrieve system information via WebSockets

The API can notify your application about changes using WebSockets. You can subscribe to most endpoints by appending `/subscribe` to the endpoint URL when using the WebSocket protocol. In general, endpoints in the `/state` namespace are intended to be subscribed to via WebSockets.

```bash
# Flight state
websocat -H="Authorization: Bearer <auth_token>" \
ws://192.168.2.100:3128/api/v1/flight/state/subscribe

# Camera state
websocat -H="Authorization: Bearer <auth_token>" \
ws://192.168.2.100:3128/api/v1/camera/state/subscribe
```

The API sends updated information over WebSockets as soon as it becomes available. The data is delivered as a sequence of WebSocket binary messages, each containing a JSON object in the same format returned by the corresponding endpoint.

## Accessing video streams

Video streams are available as H.264-encoded RTSP sources, which can be accessed using any RTSP client (eg. [VLC media player](https://www.videolan.org/vlc/)). Learn more in [Local Video Streaming (RTSP)](https://manual.fotokite.com/installation-and-integration/local-video-streaming-rtsp). The video streams are available only while the Kite is flying.

To retrieve information such as the ID, protocol, frame width, frame height, codec, and URLs for the video streams, use:

```bash
# Video streams
curl -X GET "http://192.168.2.100:3128/api/v1/videostreams" \
--oauth2-bearer <auth_token>
```

With the info provided via the API you can start consuming the RTSP video. For low-latcency streaming, we recommend e.g. using GStreamer with a pipeline configured as follows:

```bash
// GStreamer
gst-launch-1.0 rtspsrc location=rtsp://192.168.2.100:554/zoom drop-on-latency=true latency=300 ! rtph264depay ! h264parse ! avdec_h264 ! queue ! xvimagesink
```

Code examples can be found in [Video Streams](/code-examples/video-streams).

## Subscribe to system notifications

To monitor the state of the system, especially during flight, it is strongly recommended to subscribe to system notifications via webSockets. More details can be found in [Notifications](/fotokite-api/notifications).&#x20;

```bash
# Notifiactions
websocat -H="Authorization: Bearer <auth_token>" \
ws://192.168.2.100:3128/api/v1/notifications/state
```

An overview of important notifications can be found in the Fotokite Sigma User Manual under <https://manual.fotokite.com/failure-modes/messages-and-warnings>

## Remote ID

For drones with Remote ID (USA) enabled, API endpoints such as Take off require an operator to be present.

This requirement can now be fulfilled in two ways:

* By connecting a Fotokite tablet, or
* By providing operator and regulatory information via [Handoff](/fotokite-api/handoff#post-v0-handoff-control-request)

If neither is available, the system will block takeoff. The state of Remote ID can be monitored using the relevant system endpoints (e.g. `/system/state`).

More details can be found in <https://manual.fotokite.com/operational-guidelines/faa-remote-id-usa>.

## Errors

API calls that are not understood by the system or that cannot be processed are signaled using standard HTTP status code. Conditions that affect the operation of the overall system (such as inability to take off) are generally not reported using HTTP status codes. Instead, the problem will be reported asynchronously as a notification, while the original API request succeeds.

| HTTP Status Code | Description                                                                                                                                                                                                                                                                                                                |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 200              | OK (queries)                                                                                                                                                                                                                                                                                                               |
| 201, 202         | Command accepted/queued                                                                                                                                                                                                                                                                                                    |
| 400              | Bad Request, typically malformed request body or parameter values outside the permissible range                                                                                                                                                                                                                            |
| 401              | Authentication required. Provide an access token.                                                                                                                                                                                                                                                                          |
| 403              | Authenticated, but the session can't perform this operation right now, e.g. due to another client controlling the system.                                                                                                                                                                                                  |
| 404              | Invalid endpoint name or resource/component not present in the system.                                                                                                                                                                                                                                                     |
| 405              | Method not allowed, specifically includes attempts to subscribe a Websocket connection to an endpoint that does not support subscription.                                                                                                                                                                                  |
| 409              | Invalid state, the operation can't be performed  in the current operating state (e.g. rotation while the Kite is not flying).                                                                                                                                                                                              |
| 429              | Rate limited, all requests are subject to strict rate limits to ensure the reliability of the API service when interacting with misconfigured clients. In case of a 429 error, back off (0.1s-1s) and retry. Authentication failures (401) can cause more strict rate limiting, back off for 10s to reset all rate limits. |
| 503              | The operation can't be performed right now due to the system not being fully initialized yet, retry later.                                                                                                                                                                                                                 |

Most errors come with a standard JSON body that contains an error code and an error message. The error code uniquely identifies the error condition and can be used by Fotokite support to pinpoint the precise issue. The error message is provided for developers' convenience and explains what caused the error. Clients must not rely on error codes or messages to function; only the HTTP status codes are guaranteed to be stable between releases. Error messages should not be displayed to operators, they are only targeted at developers.

Any problems that should be reported to operators are presented as notifications, and can be localized using the notifications dictionary.


# Network Integration

The Fotokite system and Fotokite API can operate in different network setups depending on your needs. On this page we present supported network configurations.

Choose one of the following network setups and follow the instructions below:

* **Standalone setup**\
  Connect your client device directly to the Ground Station. \
  Select [#standalone-setup](#standalone-setup "mention")
* **Integrated setup**\
  Connect your client device and one or more Ground Stations to the same local network. \
  Select [#integrated-setup](#integrated-setup "mention")

A more detailed guide on supported network setups can be found in our user manual in [Network Integration and Setup](https://manual.fotokite.com/installation-and-integration/network-integration-and-setup).

## Standalone setup

### What is **a standalone setup**?

The Fotokite Ground Station provides its own IP network with DHCP and Internet access via the built-in modem. This network can be accessed by connecting to the Wi-Fi network provided by the Ground Station. It is also possible to connect to the Ground Station network via the Ethernet port on the Ground Station, if it is configured in "Bridged" mode.

<figure><img src="https://3669484394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXUDGlNkSLzd9Nbig1oF3%2Fuploads%2Fn6R34GGsgKUHpp03c8cd%2Fdevelopers-networking.jpg?alt=media&amp;token=fddfff98-4176-44b6-ab72-7e16661a7d21" alt=""><figcaption><p>Standalone setup</p></figcaption></figure>

### When should a **standalone setup** be used?

This can be used for development and stand-alone deployments. Controlling more than one Sigma system via Ground Station network access is not supported.

### Setup

1. Connect your client device to the Ground Station:
   1. Over Wi-Fi: Connect your client device to the Ground Station Wi-Fi network.
   2. Over Ethernet: Connect your client device over Ethernet with the Ground Station. Make sure the Ethernet port is set to "Bridged" mode in Fotokite Live - System Connect - Advanced Ground Station Settings. Also make sure you pick the correct Ethernet port if you have a Roof Top Box. See [Network Integration and Setup](https://manual.fotokite.com/installation-and-integration/network-integration-and-setup#physical-connection)
2. You can now call API endpoints using the following URLs:

```bash
# HTTP with ip and port
curl http://192.168.2.100:3128/api/v1/health

# HTTPS with ip and port
curl --insecure https://192.168.2.100:3128/api/v1/health

# HTTP with hostname
curl http://<fotokite-system-name>.sigma.fotokite-system.com/api/v1/health

# HTTPS with hostname
curl https://<fotokite-system-name>.sigma.fotokite-system.com/api/v1/health
```

## **Integrated setup**

### What is the i**ntegrated setup**?

The Fotokite system can be connected to any local network. Either via Wi-Fi or via ethernet. This network can be, for example a vehicle network, a building/office network or simply a smartphone with an enabled Wi-Fi hotspot.

<figure><img src="https://3669484394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXUDGlNkSLzd9Nbig1oF3%2Fuploads%2FjjdaIZvtKV582PBDuRhs%2Fdevelopers-networking-dhcp-nat.jpg?alt=media&amp;token=e45a6698-b78b-4dfe-a0bf-2a21e5ada972" alt=""><figcaption><p>Integrated setup</p></figcaption></figure>

### When should an **integrated network setup** be used?

We recommend this setup for any deployment that has its own upstream Internet connection. The integrated setup must be used if more than one Fotokite device should be controlled from a single client device.

### Using hostname

The Ground Station network will automatically resolve the hostname `<gsname>.sigma.fotokite-system.com` to the IP address 192.168.2.100, where all Sigma interfaces can be reached.&#x20;

The Ground Station will issue globally trusted TLS certificates for this domain name, and encrypted communication via HTTPS or RTSPS can be used seamlessly without extra setup. Despite the fully qualified domain name, all communication remains local and an internet connection is not required, apart from initial setup.

### Setup

1. Connect your client device to your local network.

{% hint style="danger" %}
The 192.168.2.X/24 IPv4 subnet is used internally by the Fotokite system. There will be address conflicts if the customer network is configured with an overlapping IP address range. This cannot be changed.
{% endhint %}

2. Connect your Fotokite Live tablet to your Ground Station over Wi-Fi. This is required for setup only.
3. Connect your Ground Station to your local network
   1. Over Wi-Fi: Select your network in Fotokite Live - System Connect - Internet over Wi-Fi.
   2. Over Ethernet: Connect your Ground Station over Ethernet with your local network. Make sure the Ethernet port is set to "NAT (DHCP)" or "NAT (Static)" mode in Fotokite Live - System Connect - Advanced Ground Station Settings.
4. If "NAT (DHCP)" is selected, the Ground Station will now automatically configure an IP address using DHCP. The IP address will be shown in Advanced Ground Station Setting&#x73;*.*&#x20;

<figure><img src="https://3669484394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXUDGlNkSLzd9Nbig1oF3%2Fuploads%2FGyX1xBcWB45F1RIWmApQ%2Fnat-dhcp.png?alt=media&amp;token=1d8bb8b0-51fa-4478-85cd-ed5d708a590a" alt=""><figcaption><p>NAT (DHCP)</p></figcaption></figure>

5. Now you can try to access the API (unencrypted using --insecure) using the displayed IP address shown in Advanced Ground Station Settings (as in the screenshot above).

<pre class="language-bash"><code class="lang-bash"><strong># HTTPS (without certificate verification)
</strong>curl --insecure https://10.21.0.120/api/v1/health
</code></pre>

6. Setup an encrypted connection\
   \
   The Ground Station will issue globally trusted TLS certificates for the domain name `<gsname>.sigma.fotokite-system.com`, and encrypted communication via HTTPS or RTSPS can be used. Despite the fully qualified domain name, all communication remains local and an internet connection is not required, apart from initial setup.
7. Determine your Fotokite system name. You can find it in Fotokite Live > System Connect.
8. Setup a local hostname binding for \<fotokite-system-name>.sigma.fotokite-system.com on your client device or your network router. Usually the easiest is to amend the hosts file \
   Windows: C:\Windows\System32\drivers\etc\hosts\
   MacOS or Linux: /etc/hosts

<figure><img src="https://3669484394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXUDGlNkSLzd9Nbig1oF3%2Fuploads%2F1WjbR3foJexnLUvoUyji%2Fhost-name.png?alt=media&amp;token=71454b50-680f-4fbb-a81b-e23817cf915e" alt=""><figcaption><p>Edited /etc/hosts file on MacOS for Ground Station G028B</p></figcaption></figure>

Now you can try to access the API (encrypted) using the hostname as shown below.

```bash
# HTTPS
curl https://<fotokite-system-name>.sigma.fotokite-system.com/api/v1/health
```


# Authentication and Security

## Authentication

The authentication mechanism ensures proper security and access control. Most API endpoints are protected and scoped, meaning each request to a protected endpoint must include a valid bearer token.

### Get a token via Token Management

The simplest way to obtain a token is through our Token Management system. This method is recommended if you manage fewer than five systems.

{% stepper %}
{% step %}
Connect a computer with a web browser to the same network as your Fotokite system. We recommend using Wi-Fi.
{% endstep %}

{% step %}
Open the following URL in your browser.

```bash
http://192.168.2.100:3128/api/token_management
```

<figure><img src="https://3669484394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXUDGlNkSLzd9Nbig1oF3%2Fuploads%2F1gRTT2HdSvg0vzPy3Wiw%2Ftoken-management.jpg?alt=media&amp;token=edae2782-3a9c-4142-af80-90c58cf4522c" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Click the Create API token button to create a new token.

* Name: The name will help you organize your tokens. It will also be visible in Fotokite Live whenever your app uses that token to perform any controls.
* Scope: Token scopes determine which endpoint(s) an API token can access.
  * read: Access to all endpoints for retrieving information, except `/control` endpoints.
  * control: Access to `/control` endpoints.
  * experimental: Access to experimental and unstable features.
    {% endstep %}

{% step %}
The token (bearer token) is used to authenticate all subsequent requests to protected endpoints.

```bash
# System information
curl -X GET "http://192.168.2.100:3128/api/v1/system/info" \
--oauth2-bearer <auth_token>
```

{% endstep %}

{% step %}
Tokens can be invalidated via [Authentication](/fotokite-api/authentication#post-v0-auth-token-invalidate). Once a token is invalidated, you must request a new one using Token Management.

Good to know: This token does not expire.
{% endstep %}
{% endstepper %}

### Get a token via API Key

We recommend using API keys if you have more than 5 systems. Please contact Fotokite to obtain an API key.

<a href="https://fotokite.com/contact/contact-form/" class="button primary">Get API Key</a>

{% stepper %}
{% step %}
To obtain a token, send a request using [Authentication](/fotokite-api/authentication#post-v0-auth-token-request) by including your API Key as client\_secret.# Request token

```bash
# Request token with scopes
curl -X POST "http://192.168.2.100:3128/api/v1/auth/token/request" \
  -H "Content-Type: application/json" \
  -d '{
    "client_secret": "ApiKey123"
    "scope": "read control"
  }'
```

{% endstep %}

{% step %}
The token (bearer token) is used to authenticate all subsequent requests to protected endpoints.

```bash
# System information
curl -X GET "http://192.168.2.100:3128/api/v1/system/info" \
--oauth2-bearer <auth_token>
```

Tokens can be invalidated via [Authentication](/fotokite-api/authentication#post-v0-auth-token-invalidate). Once a token is invalidated, you must request a new one using your API key.

Good to know: A token generated with an API key expires after 24 hours.
{% endstep %}
{% endstepper %}

## Security

### TLS Certificates used by the Fotokite API

For use with HTTPS, the Sigma system issues certificates under the domain `*.sigma.fotokite-system.com`, for example `g2553ah.sigma.fotokite-system.com`. These certificates are signed by globally trusted certificate authorities (Google Trust Services) and assure that you are actually connected to this specific Fotokite Sigma.

However, while the certificates are globally trusted, the domain names like `g2553ah.sigma.fotokite-system.com` *do not* globally refer to the specific Sigma system and *cannot* be used to reach a Sigma system from the Internet. Instead, choose one or more of the following options to validate the certificate:

* Add a DNS override rule to your network, which maps `<gsname>.sigma.fotokite-system.com` to the IP address of the respective system. Combine this with the "NAT (Static)" setting to configure a static IP address.
* Or access the Sigma system through its assigned IP address, but instruct your TLS implementation to validate against a specific hostname, `<gsname>.sigma.fotokite-system.com`. (Refer to the provided Python code for an example).
* Or access the Sigma system through its assigned IP address, but instead of PKI validation, check the key fingerprint and compare it with a stored value (*TLS Public Key Pinning*).

#### Certificate renewal

The TLS certificates will be issued for a lifetime of 3 months and will automatically be renewed every month. The process requires that the Ground Station is powered on and connected to the internet regularly. To ensure reliable operation while completely offline, ensure that

* your client code *does not* respect certificate expiration. The Sigma system will keep using expired certificates if they can't be renewed, but your client also needs to keep accepting expired certificates.
* or your client code uses key pinning and the Sigma system is *never* connected to the internet unexpectedly. Once the system is connected to the Internet e.g. for system updates, it will renew the certificates and the pinned keys must be updated.

For best reliability and security, combine both approaches:

* When the system presents an unknown certificate in an API call, validate that it is correctly signed to a Common Name under `*.sigma.fotokite-system.com` by a public CA.
* If the certificate is valid, store it as a pinned key for this system, and keep trusting this key beyond expiration until a new, valid certificate is presented.

If you have questions regarding certificate validation or require long-lived certificates or certificates signed by specific CAs, please contact us to find a solution.


# Code Examples

These examples serve as a foundation, and building more complex or customized solutions is fully in your hands, giving you the flexibility to create what best fits your needs.

We’ve created also a GitHub repository with sample code for various workflows using the API.

<a href="https://github.com/fotokite/fotokite-api" class="button primary">API Example Repo</a>


# System Information

This section explains how to use system endpoints to identify the connected system, access component information, and subscribe to real-time updates via WebSockets.

For more details, see [System](/fotokite-api/system) or the [GitHub repository](https://github.com/fotokite/fotokite-api/tree/main/example/).

### Get system info

Retrieve basic system information, such as:

* System ID
* Timezone
* Hardware configuration (main board components)

```python
def system_info(access_token: str = "") -> SystemMessage:
    """Fetches system information.

    Args:
        access_token: Bearer token for API authentication. Defaults to "".

    Returns:
        Parsed system information message if the request is successful.
        Empty dictionary if an error occurs.

    Raises:
        requests.HTTPError: If the HTTP request fails with a non-200 status code.
        Exception: For any other exceptions encountered during the request.
    """
    try:
        response = requests.get(
            f"{BASE_REST_API_URL}/system/info",
            headers={"Authorization": f"Bearer {access_token}"},
        )
        if response.status_code == 200:
            return cast(SystemMessage, response.json())
        else:
            response.raise_for_status()
    except Exception as e:
        logging.error(f"Error fetching system info: {e}")

    return {}
```

### Subscribe system state

This example shows how to subscribe to frequently changing data, such as:

* Ground station battery level
* Kite battery level
* GPS status

It enables real-time monitoring of the system’s overall health and readiness.

```python
def system_telemetry(
    on_message_callback: Callable[[SystemMessage], None],
    access_token: str = "",
    max_messages: int | None = None,
) -> None:
    """Subscribes to system info telemetry

    Args:
        on_message_callback: A callback function to handle incoming messages.
        access_token: The authentication token to use in the websocket connection.
        max_messages: The maximum number of messages to process. Defaults to None.
    """
    ws_url = f"{BASE_WEBSOCKET_API_URL}/system/state/subscribe?access_token={access_token}"
    try:
        with connect(
            ws_url, additional_headers={"Authorization": f"Bearer {access_token}"}
        ) as websocket:
            logging.info("Connected to system telemetry")
            count = 0
            while True:
                message = websocket.recv()
                data = json.loads(message)

                on_message_callback(data)

                count += 1
                if max_messages is not None and count >= max_messages:
                    break
    except Exception as e:
        logging.error(f"Error in system telemetry: {e}")
```


# Notifications

To monitor the state of the system, especially during flight, it is strongly recommended to subscribe to system notifications via WebSockets.

For more details, see [#notifications](#notifications "mention") or the [GitHub repository](https://github.com/fotokite/fotokite-api/tree/main/example/).

### Subscribe notifications

The example demonstrates how to subscribe to live notifications to receive important system events, such as:

* Safety warnings
* System errors

```python
def notifications_telemetry(
    on_message_callback: Callable[[Notification], None],
    access_token: str,
    max_messages: int | None = None,
) -> None:
    """Subscribes to notifications telemetry.

    Args:
        on_message_callback: A callback function to handle incoming messages.
        access_token: The authentication token to use in the websocket connection.
        max_messages: The maximum number of messages to process. Defaults to None.
    """
    ws_url = f"{BASE_WEBSOCKET_API_URL}/notifications/subscribe"
    try:
        with connect(
            ws_url, additional_headers={"Authorization": f"Bearer {access_token}"}
        ) as websocket:
            logging.info("Connected to notifications telemetry")
            count = 0
            while True:
                message = websocket.recv()
                data = json.loads(message)
                on_message_callback(data)

                count += 1
                if max_messages is not None and count >= max_messages:
                    break
    except Exception as e:
        logging.error(f"Error in notifications telemetry: {e}")
```

An overview of important notifications can be found in the Fotokite Sigma User Manual under <https://manual.fotokite.com/failure-modes/messages-and-warnings>

### Get notification dictionary

A dictionary of all available notifications is provided in the following format:

* Code
* Severity
* Message (a human-readable interpretation of the notification for display in interfaces)

```python
def dictionary(access_token: str) -> dict[str, object]:
    """Fetches the notifications dictionary.

    Args:
        access_token: The authentication token to use in the request.

    Returns:
        A dictionary containing notification definitions with their codes and descriptions.
        If the request fails or an exception occurs, logs the error and returns an empty dictionary.

    Raises:
        requests.HTTPError: If the HTTP request fails with a status code other than 200.
        Exception: For any other exceptions encountered during the request.
    """
    try:
        headers = {"Authorization": f"Bearer {access_token}"}
        response = requests.get(
            f"{BASE_REST_API_URL}/notifications/dictionary", headers=headers
        )
        if response.status_code == 200:
            return cast(dict[str, object], response.json())
        else:
            response.raise_for_status()
    except Exception as e:
        logging.error(f"Error fetching notifications dictionary: {e}")

    return {}
```


# Flight Telemetry

This section explains how to use the flight control capabilities of the API. It includes examples for subscribing to live data and sending flight commands, providing precise, real-time control of the system.

For more details, see [Flight](/fotokite-api/flight) or the [GitHub repository](https://github.com/fotokite/fotokite-api/tree/main/example/).

### Subscribe flight state

Provides real-time data about the system’s operational status. By using the flight state information, applications can monitor system performance, ensure operation within safe limits, and more.

```python
def flight_telemetry(
 on_message_callback: Callable[[dict[str, object]], None],
    access_token: str = "",
    max_messages: int | None = None,
) -> None:
    """Subscribes to flight telemetry updates from the System.
​
    Args:
        on_message_callback: Callback function to handle incoming telemetry messages.
        access_token: The authentication token to use in the websocket connection.
        max_messages: Maximum number of messages to receive before unsubscribing. Defaults to None(read forever).
    """
    ws_url = f"{BASE_WEBSOCKET_API_URL}/telemetry/flight/subscribe"
    try:
        with connect(
            ws_url, additional_headers={"Authorization": f"Bearer {access_token}"}
        ) as websocket:
            logging.info("Connected to flight telemetry")
            count = 0
            while True:
                message = websocket.recv()
                data = json.loads(message)
                on_message_callback(data)
                count += 1
                if max_messages is not None and count >= max_messages:
                    break
    except Exception as e:
        logging.error(f"Error in flight telemetry: {e}")
```

### **Flight control**

To control the system, you must use the endpoints in the `/control` namespace. It is important to note that these endpoints are part of the Control Handoff mechanism. Control Handoff ensures that only one client can control the system at any given time. Before using any endpoint in the `/control` namespace, the API must first request control.

The API does not block or wait for a command to complete. Command execution must be verified through flight state data, which indicates changes in the aircraft’s status.

The example demonstrates how to send a take off command.

```python
def take_off(access_token: str) -> bool:
    """Sends a take off command to the Ground Station.
    Args:
        access_token: The authentication token to use in the request.
    Returns:
        True if the take off command was sent successfully (HTTP 200), False otherwise.
        This does not guarantee that the Kite will take off, only that the command was sent successfully.
        To check if the Kite has taken off, monitor the flight telemetry.​
    """
    try:
        # Tries to retrieve handoff control before sending a command. If handoff retrieval fails then it will raise an exception.
        retrieve_handoff(access_token)
        
        headers = {"Authorization": f"Bearer {access_token}"}
        response = requests.post(
            f"{BASE_REST_API_URL}/flight/take_off", headers=headers
        )
​
        if response.status_code == 200:
            logging.info("Take off command sent successfully.")
            return True
        else:
            logging.error(f"Error sending take off command: {response.text}")
    except Exception as e:
        logging.error(f"Exception in take_off: {e}")
        
    return False
```


# Video Streams

This section describes how to work with the system’s video streams. The streams use the RTSP protocol and can be converted to other formats as needed. Tools such as GStreamer or FFmpeg can efficiently pipe the source stream into different formats.

For more details, see [Video Streams](/fotokite-api/video-streams) or the [GitHub repository](https://github.com/fotokite/fotokite-api/tree/main/example/).

### List video streams

Lists all active video streams. This data is generally stable and changes only when a stream’s status changes (e.g., on/off).

```python
def list_videostreams(access_token: str = "") -> VideoStreamMessage:
    """Fetches the list of available video streams.

    Args:
        access_token: Bearer token for API authentication. Defaults to "".

    Returns:
        Parsed JSON response containing video stream information if successful.
        An empty dictionary if an error occurs.

    Raises:
        requests.HTTPError: If the response status code is not 200.
        Exception: For any other errors during the request.
    """
    try:
        response: requests.Response = requests.get(
            f"{BASE_REST_API_URL}/videostreams",
            headers={"Authorization": f"Bearer {access_token}"},
        )
        if response.status_code == 200:
            return cast(VideoStreamMessage, response.json())
        else:
            response.raise_for_status()
    except Exception as e:
        logging.error(f"Error fetching video stream info: {e}")

    return {}
```

### Change zoom level

Certain aspects of the video streams can be adjusted, such as zoom level and thermal color palette. These adjustments are stream-specific, and not all commands apply to all streams—for example, the zoom command applies only to the zoom video stream. Ensure that the correct stream identifier is used as specified above.

The example demonstrates how to change the zoom level.

```python
def zoom(
    access_token: str = "", stream_id: str = "zoom", zoom_level: float = 1.0
) -> bool:
    """Adjusts the zoom level of a specified video stream.

    Args:
        access_token: Bearer token for API authentication.
        stream_id: Identifier of the video stream to zoom. Defaults to "zoom".
        zoom_level: Desired zoom level. Defaults to 1.0.

    Returns:
        True if the zoom level was successfully changed, False otherwise.

    Raises:
        requests.HTTPError: If the API request fails with a non-200 status code.
    """
    try:
        # Tries to retrieve handoff control before sending a command. If handoff retrieval fails then it will raise an exception.
        retrieve_handoff(access_token)
        
        response: requests.Response = requests.post(
            f"{BASE_REST_API_URL}/videostreams/{stream_id}/control/zoom",
            json={"zoom_level": zoom_level},
            headers={"Authorization": f"Bearer {access_token}"},
        )
        if response.status_code == 200:
            logging.info("Zoom level changed to %s", zoom_level)
            return True
        else:
            response.raise_for_status()
    except Exception as e:
        logging.error(f"Error changing zoom level: {e}")

    return False
```

The example demonstrates how to change the thermal color palette of the thermal video stream.

```python
def set_palette(
    access_token: str = "", stream_id: str = "thermal", palette: str = "Rainbow"
) -> bool:
    """Sets the thermal color palette for a specified video stream.

    Args:
        access_token: The access token for authentication. Defaults to an empty string.
        stream_id: The ID of the video stream to modify. Defaults to "thermal".
        palette: The name of the thermal color palette to set. Defaults to "Rainbow".

    Returns:
        True if the palette was successfully changed, False otherwise.

    Raises:
        requests.HTTPError: If the HTTP request fails with a non-200 status code.
    """
    try:
        # Tries to retrieve handoff control before sending a command. If handoff retrieval fails then it will raise an exception.
        retrieve_handoff(access_token)
        
        response: requests.Response = requests.post(
            f"{BASE_REST_API_URL}/videostreams/{stream_id}/control/palette",
            json={"thermal_color_palette": palette},
            headers={"Authorization": f"Bearer {access_token}"},
        )
        if response.status_code == 200:
            logging.info("Palette changed to %s", palette)
            return True
        else:
            response.raise_for_status()
    except Exception as e:
        logging.error(f"Error changing zoom level: {e}")

    return False
```

### GStreamer - HLS

This example demonstrates how to consume thermal and color RTSP video streams, create a GStreamer pipeline, and serve the resulting HLS streams over HTTP.

```python
import http.server
import logging
import os
import signal
import socketserver
import subprocess
import sys
import threading
from typing import Any, List, Tuple

logging.basicConfig(
    level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s"
)

""" CORS support for browsers to access HLS streams """


class CORSRequestHandler(http.server.SimpleHTTPRequestHandler):
    def end_headers(self) -> None:
        self.send_header("Access-Control-Allow-Origin", "*")
        self.send_header("Access-Control-Allow-Methods", "GET, OPTIONS")
        self.send_header(
            "Access-Control-Allow-Headers", "Range, Content-Type, Origin, Accept"
        )
        super().end_headers()

    def do_OPTIONS(self) -> None:
        self.send_response(200, "ok")
        self.end_headers()


class ReusableTCPServer(socketserver.TCPServer):
    allow_reuse_address = True


def start_gstreamer(rtsp_url: str, hls_dir: str) -> subprocess.Popen[bytes]:
    """Starts a GStreamer pipeline to stream RTSP video and convert it to HLS segments.

    Args:
        rtsp_url: The RTSP URL of the video stream source.
        hls_dir: The directory where HLS segments and playlist will be stored.

    Returns:
        The process running the GStreamer pipeline.
    """
    playlist_path: str = os.path.join(hls_dir, "playlist.m3u8")

    if not os.path.exists(hls_dir):
        os.makedirs(hls_dir)

    cmd: List[str] = [
        "gst-launch-1.0",
        "rtspsrc",
        f"location={rtsp_url}",
        "latency=0",
        "!",
        "rtph264depay",
        "!",
        "h264parse",
        "!",
        "mpegtsmux",
        "!",
        f"hlssink",
        f"location={hls_dir}/segment%05d.ts",
        f"playlist-location={playlist_path}",
        "target-duration=2",
        "max-files=5",
    ]

    process = subprocess.Popen(
        cmd, stdout=sys.stdout, stderr=sys.stderr, preexec_fn=os.setsid
    )
    logging.info(f"Started GStreamer for {rtsp_url}")
    return process


def start_http_server(
    hls_dir: str, port: int
) -> Tuple[threading.Thread, socketserver.TCPServer]:
    """Starts an HTTP server to serve files from the specified HLS directory with CORS support.

    Args:
        hls_dir: Path to the directory containing HLS files to be served.
        port: Port number on which the HTTP server will listen.

    Returns:
        A tuple containing the thread running the server and the server instance itself.
    """
    os.chdir(hls_dir)

    httpd: ReusableTCPServer = ReusableTCPServer(("", port), CORSRequestHandler)

    def serve() -> None:
        logging.info(f"Serving HLS on http://localhost:{port}/playlist.m3u8")
        try:
            httpd.serve_forever()
        except Exception as e:
            logging.error(f"HTTP server error: {e}")

    thread = threading.Thread(target=serve, daemon=True)
    thread.start()
    return thread, httpd


def main() -> None:
    """Starts GStreamer processes and HTTP servers for multiple RTSP streams, manages their lifecycles, and handles graceful shutdown on SIGINT or SIGTERM.

    The function:
    - Configures multiple RTSP streams and corresponding HLS output directories and HTTP ports.
    - Launches GStreamer processes to convert RTSP streams to HLS.
    - Starts HTTP servers to serve the HLS streams.
    - Registers signal handlers to gracefully terminate all processes and servers on shutdown signals.
    - Waits for all server threads to finish before exiting.

    """

    # Mapping of RTSP streams to HLS directories and ports
    configs: List[Tuple[str, str, str, int]] = [
        ("Thermal", "rtsp://192.168.2.100:5012/video", "/tmp/hlsThermal", 8082),
        ("Color", "rtsp://192.168.2.100:5010/video", "/tmp/hlsColor", 8083),
    ]

    processes: List[subprocess.Popen[bytes]] = []
    servers: List[socketserver.TCPServer] = []
    threads: List[threading.Thread] = []

    # Start GStreamer processes and HTTP servers for each RTSP stream
    for _, rtsp_url, hls_dir, port in configs:
        proc = start_gstreamer(rtsp_url, hls_dir)
        thread, httpd = start_http_server(hls_dir, port)
        processes.append(proc)
        servers.append(httpd)
        threads.append(thread)

    # Handle graceful shutdown on SIGINT or SIGTERM
    def shutdown(signum: int, frame: Any) -> None:
        logging.info("Received shutdown signal, stopping everything...")

        # Stop GStreamer processes
        for proc in processes:
            try:
                pgid: int = os.getpgid(proc.pid)
                os.killpg(pgid, signal.SIGKILL)
                logging.info(f"Stopped GStreamer process group {pgid}")
            except Exception as e:
                logging.error(f"Error stopping GStreamer process: {e}")

        # Stop HTTP servers
        for httpd in servers:
            try:
                httpd.shutdown()
                logging.info("HTTP server shut down")
            except Exception as e:
                logging.error(f"Error shutting down server: {e}")

        sys.exit(0)

    signal.signal(signal.SIGINT, shutdown)
    signal.signal(signal.SIGTERM, shutdown)

    # Wait for threads to finish (they will stop after shutdown)
    try:
        for thread in threads:
            thread.join()
    except KeyboardInterrupt:
        shutdown(signal.SIGINT, None)


if __name__ == "__main__":
    main()
```

### FFMPEG - HLS

A similar example using FFmpeg for the pipeline can be found in the [GitHub repository](https://github.com/fotokite/fotokite-api/blob/main/example/python/fotokite_api/streamer/ffmpeg.py).


# Demo

The demo identifies the system and establishes separate telemetry WebSocket connections for monitoring:

* System information
* Flight telemetry

It then performs the following sequence of controls:

* Take off
* Ascend to a specified altitude
* Rotate +180°
* Rotate −180°
* Land

After completing the sequence, the demo waits briefly, shuts down the telemetry listeners, and exits.

For more details, see the [GitHub repository](https://github.com/fotokite/fotokite-api/tree/main/example/).

```python
import logging
import random
import time

from fotokite_api.camera.camera import set_palette, zoom
from fotokite_api.flight.flight import (
    land,
    rotate_by_angle,
    set_altitude,
    take_off,
    wait_for,
)
from fotokite_api.utils import API_KEY, retrieve_auth_token

color_palettes = [
    "BlackHot",
    "WhiteHot",
    "Ironbow",
    "Rainbow",
    "Arctic",
    "Lava",
    "Hottest",
]


def demo_sequential() -> None:
    """
    This demo sends commands and waits for them to complete, one after the
    other. The waiting uses a Websocket subscription under the hood, but this
    is hidden by an abstraction.

    Notifications are not monitored, code like this should only be used with
    Fotokite Live open in parallel.
    """

    # Retrieve an access token
    access_token = retrieve_auth_token(API_KEY)
    if access_token is None:
        logging.error("Failed to retrieve authentication token. Exiting.")
        return
    
    try:
        # Tries to retrieve handoff control before sending a command. If handoff retrieval fails then it will raise an exception.
        retrieve_handoff(access_token)
    except Exception as e:
        logging.error(f"Failed to retrieve handoff: {e}")
        return

    wait_for(access_token, state="StandBy")
    take_off(access_token)
    # the sleep after each command is currently required to avoid a race
    # condition where the command has *not started yet* when running the
    # `wait_for`, which would make it exit immediately
    wait_for(access_token, state="Flying")
    set_altitude(2, access_token)
    time.sleep(1)
    rotate_by_angle(access_token, 0, 20)
    wait_for(access_token, state="Flying")
    time.sleep(1)
    zoom(access_token, "zoom", 2.0)
    zoom(access_token, "zoom", 2.5)
    set_palette(random.choice(color_palettes))
    time.sleep(1)
    zoom(access_token, "zoom", 5.0)
    time.sleep(1)
    wait_for(access_token, state="Flying")
    rotate_by_angle(access_token, 180, 0)
    time.sleep(1)
    wait_for(access_token, state="Flying")
    rotate_by_angle(access_token, -180, 0)
    zoom(access_token, "zoom", 1)
    time.sleep(1)
    wait_for(access_token, state="Flying")
    land(access_token)
    time.sleep(1)
    wait_for(access_token, state="StandBy")


if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    demo_sequential()

```

Stateful demo with telemetry logging

```python
import json
import logging
import threading
import time
from typing import TypedDict

from fotokite_api.flight.flight import (
    abort,
    flight_telemetry,
    land,
    rotate_by_angle,
    set_altitude,
    take_off,
)
from fotokite_api.notifications.notifications import start_telemetry_with_logging
from fotokite_api.system.system import system_info, system_telemetry
from fotokite_api.utils import API_KEY, retrieve_auth_token


class FlightState(TypedDict):
    altitude_changed: bool
    first_rotation: bool
    second_rotation: bool
    landing: bool


state: FlightState = {
    "altitude_changed": False,
    "first_rotation": False,
    "second_rotation": False,
    "landing": False,
}


def demo_flight() -> None:
    """Demonstrates a flight sequence using the Fotokite API.

    This function performs the following steps:
        1. Configures logging for informational output.
        2. Retrieves and logs system information (Identity, components etc...).
        3. Starts telemetry threads for flight, system, and notifications.
        4. Sends a takeoff command and logs the result.
        6. Performs a sequence of maneuvers:
        - Sets altitude to 2 meters.
        - Rotates by 180 degrees.
        - Rotates back by -180 degrees.
        - Lands the Fotokite.
        5. If takeoff fails, aborts the mission and exits.
        6. Keeps the main thread alive, monitoring for landing state.
        7. After landing, waits to collect final telemetry data.
    """
    logging.basicConfig(level=logging.INFO)

    # Retrieve an access token
    access_token = retrieve_auth_token(API_KEY)
    if access_token is None:
        logging.error("Failed to retrieve authentication token. Exiting.")
        return
        
    try:
        # Tries to retrieve handoff control before sending a command. If handoff retrieval fails then it will raise an exception.
        retrieve_handoff(access_token)
    except Exception as e:
        logging.error(f"Failed to retrieve handoff: {e}")
        return

    # Identify the system
    info = system_info(access_token)
    logging.info("System Info:\n%s", json.dumps(info, indent=2))

    # Start telemetry threads
    flight_thread = threading.Thread(
        target=flight_telemetry,
        args=(handle_flight, access_token),
        daemon=True,
    )
    flight_thread.start()

    system_thread = threading.Thread(
        target=system_telemetry,
        args=(
            lambda data: logging.info(
                "System Telemetry:\n%s", json.dumps(data, indent=2)
            ),
            access_token,
        ),
        daemon=True,
    )
    system_thread.start()

    notifications_thread = threading.Thread(
        target=start_telemetry_with_logging,
        args=(access_token,),
        daemon=True,
    )
    notifications_thread.start()

    # Allow telemetry to start
    time.sleep(2)

    if take_off(access_token):
        logging.info("Takeoff command sent.")
    else:
        logging.error("Takeoff failed. Aborting mission.")
        abort(access_token)
        return

    # Keep the main thread alive to process telemetry updates
    while not state["landing"]:
        time.sleep(1)

    # Final wait after landing to collect telemetry
    time.sleep(10)


def handle_flight(data: dict[str, object], access_token: str) -> None:
    """Handles flight telemetry data and executes flight commands based on the current flight state."""

    logging.info("Flight Telemetry:\n%s", json.dumps(data, indent=2))

    flight_state = data.get("flight_state", "Unknown")
    is_changing_altitude = data.get("is_changing_altitude", False)
    is_rotating = data.get("is_rotating", False)

    if flight_state != "Flying":
        return

    if not state["altitude_changed"]:
        logging.info("Setting altitude to 2 meters.")
        if set_altitude(2, access_token):
            logging.info("Altitude set command sent.")
            state["altitude_changed"] = True

    elif not state["first_rotation"] and not is_changing_altitude:
        logging.info("Rotating by 180 degrees.")
        if rotate_by_angle(access_token, 180, 0):
            logging.info("Rotation command (180 deg) sent.")
            state["first_rotation"] = True

    elif not state["second_rotation"] and not is_rotating and not is_changing_altitude:
        logging.info("Rotating back by -180 degrees.")
        if rotate_by_angle(access_token, -180, 0):
            logging.info("Rotation command (-180 deg) sent.")
            state["second_rotation"] = True

    elif not state["landing"] and not is_rotating and not is_changing_altitude:
        logging.info("Landing now.")
        if land(access_token):
            logging.info("Landing command sent.")
            state["landing"] = True


if __name__ == "__main__":
    demo_flight()

```


# Get Support

Please us our Support form to get in contact with us.

<a href="https://fotokite.com/support/" class="button primary">Get Support</a>


# Changelog

## api 1.1.2

Release Date: 2026-07-29

|              | Version |
| ------------ | ------- |
| Fotokite API | 1.1.2   |

We have included the following new features and improvements:

**Total kite flight hours**

New total kite flight hours have been added. See [Flight](/fotokite-api/flight#get-v1-flight-info)

**New Rooftop Box endpoints**

New Rooftop Box related endpoints have been added.

* The Rooftop Box lids can be opened and closed. See [System](/fotokite-api/system#post-v1-system-control-open_rtb_lids)
* The current status of the parking brake interface and the safety land button can be read. See [System](/fotokite-api/system#get-v1-system-state)

**Updated Plugin State endpoint**

The plugin status endpoint has been updated.

* A warning status has been added. See [Authentication](/fotokite-api/authentication#post-v1-auth-plugin-update)
* Free text can now be displayed for "Error", "Warning" and "Connected" state.

**Deprecations**

The Plugin State endpoint has been updated with new fields for self-reported plugin status. See [Authentication](/fotokite-api/authentication#post-v1-auth-plugin-update)

The existing `plugin_id` and `state` request fields remain supported for backward compatibility but are deprecated and will be removed in a future release. Integrations should migrate to:

* `self_status`
* `self_status_text`

## api 1.0.0

Release Date: 2026-04-15

|              | Version |
| ------------ | ------- |
| Fotokite API | 1.0.0   |

This release brings the Fotokite API from preview to stable Version 1.0. Additionally, we have included the following new features and improvements:

**HTTPS Support**

The Fotokite API now supports HTTPS, enabling secure communication. HTTPS access is also allowed from upstream networks, which simplifies system integration.

**New Video Server**

Our new video server supports encrypted traffic (rtsps), reduces latency, and improves compatibility. Stream status (camera on/off) will be reported more reliably.

**Rate Limiting**

Rate limiting has been introduced to enhance security and maintain system integrity.

**NAT Mode Support**

The Fotokite API can now be used when the Ground Station is configured in NAT mode.

**Camera 1st Generation Support**

The Fotokite API now supports the legacy Camera 1st Generation.

**Handoff Control and Remote ID (US)**

When using request control, all information required for compliance with RemoteID (such as operator location) can be transmitted. This enables the implementation of user interfaces for RemoteID compliant operation without requiring a Fotokite control tablet. See: [Handoff](/fotokite-api/handoff#post-v0-handoff-control-request)

**Additional Fixes and Updates**

* Added propeller type in [System](/fotokite-api/system#get-v0-system-info)
* Added video stream URL in [Video Streams](/code-examples/video-streams)

## api-preview 0.5.0

Release Date: 2026-01-07

|                      | Version |
| -------------------- | ------- |
| Fotokite API Preview | 0.5.0   |

The current implementation, including endpoints, definitions, and example code, is still under active development and subject to change. Please be aware that details may be updated before the final version.

Currently, our API is compatible with [Camera 2nd Generation](https://manual.fotokite.com/system-profile/camera#camera-2nd-generation). Compatibility for [Camera 1st Generation](https://manual.fotokite.com/system-profile/camera#camera-1st-generation) will be available in a later version.

<table><thead><tr><th valign="top">Category</th><th valign="top">Endpoint</th><th>Status</th></tr></thead><tbody><tr><td valign="top"><a href="/fotokite-api/health">Health</a></td><td valign="top"><a href="/fotokite-api/health#get-v0-health">Get health status</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"><a href="/fotokite-api/authentication">Authentication</a></td><td valign="top"><a href="/fotokite-api/authentication#post-v0-auth-token-request">Request a token</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/authentication#post-v0-auth-token-invalidate">Invalidate a token</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/authentication#get-v0-auth-tokens">Get active tokens</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/authentication#post-v0-auth-plugin-update">Update plugin state</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"><a href="/fotokite-api/notifications">Notifications</a></td><td valign="top"><a href="/fotokite-api/notifications#get-v0-notifications">Get notifications</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/notifications#get-v0-notifications-dictionary">Get notifications Dictionary</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"><a href="/fotokite-api/handoff">Handoff</a></td><td valign="top"><a href="/fotokite-api/handoff#get-v0-handoff-state">Get handoff control state</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/handoff#post-v0-handoff-control-request">Request control</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/handoff#post-v0-handoff-control-release">Release control</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/handoff#post-v0-handoff-control-override">Override control</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"><a href="/fotokite-api/system">System</a></td><td valign="top"><a href="/fotokite-api/system#get-v0-system-info">Get system information</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/system#get-v0-system-state">Get system state</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"><a href="/fotokite-api/flight">Flight</a></td><td valign="top"><a href="/fotokite-api/flight#get-v0-flight-info">Get flight info</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/flight#get-v0-flight-state">Get flight state</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/flight#post-v0-flight-control-take_off">Take off</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/flight#post-v0-flight-control-land">Land</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/flight#post-v0-flight-control-abort">Abort take off or landing</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/flight#post-v0-flight-control-altitude">Set target altitude</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/flight#post-v0-flight-control-altitude_soft_max">Set flight max altitude (soft limit)</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"><a href="/fotokite-api/camera">Camera</a></td><td valign="top"><a href="/fotokite-api/camera#get-v0-camera-info">Get camera info</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/camera#get-v0-camera-state">Get camera state</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/camera#post-v0-camera-control-rotate_by_angle">Rotate by angle</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/camera#post-v0-camera-control-rotate_to_angle">Rotate to angle</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/camera#post-v0-camera-control-rotate_with_speed">Rotate with speed</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"><a href="/fotokite-api/video-streams">Video streams</a></td><td valign="top"><a href="/fotokite-api/video-streams#get-v0-videostreams">Get video streams</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/video-streams#get-v0-videostreams-stream_id-state">Get video stream state</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/video-streams#post-v0-videostreams-stream_id-control-zoom">Set zoom</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/video-streams#post-v0-videostreams-stream_id-control-palette">Set thermal color palette</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"><a href="/fotokite-api/recordings">Recordings</a></td><td valign="top"><a href="/fotokite-api/recordings#get-v0-recordings">Get video recording</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/recordings#get-v0-recordings-state">Get video recorder state</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/recordings#get-v0-recordings-recording_id">Get video recording</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/recordings#delete-v0-recordings-recording_id">Delete video recording</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/recordings#get-v0-recordings-recording_id-file_id">Download video</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/recordings#post-v0-recordings-control-start">Start video recording</a></td><td><mark style="color:green;">Implemented</mark></td></tr><tr><td valign="top"></td><td valign="top"><a href="/fotokite-api/recordings#post-v0-recordings-control-stop">Stop video recording</a></td><td><mark style="color:green;">Implemented</mark></td></tr></tbody></table>


# Health

## Get health status

> Returns the health status and the version of the Fotokite API.

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{}],"paths":{"/health":{"get":{"tags":["Health"],"summary":"Get health status","description":"Returns the health status and the version of the Fotokite API.","responses":{"200":{"description":"API is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"500":{"description":"API is not healthy","content":{"application/json":{"schema":{"type":"string"}}}}}}}},"components":{"schemas":{"HealthResponse":{"type":"object","description":"Health response","required":["status","api_version"],"properties":{"status":{"description":"Health status","type":"string"},"api_version":{"description":"SemVer version of the Fotokite API.","type":"string"}}}}}}
```

## Get health status

> Returns the health status and the version of the Fotokite API.

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{}],"paths":{"/v1/health":{"get":{"tags":["Health"],"summary":"Get health status","description":"Returns the health status and the version of the Fotokite API.","responses":{"200":{"description":"API is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"500":{"description":"API is not healthy","content":{"application/json":{"schema":{"type":"string"}}}}}}}},"components":{"schemas":{"HealthResponse":{"type":"object","description":"Health response","required":["status","api_version"],"properties":{"status":{"description":"Health status","type":"string"},"api_version":{"description":"SemVer version of the Fotokite API.","type":"string"}}}}}}
```


# Authentication

## Request a token

> Initiate a request to obtain an authentication token for accessing protected API endpoints. In order to perform authenticated operations, you must first obtain a token by calling this endpoint. If the request is denied, Fotokite Live may prompt the operator for authorization, depending on system configuration. The Fotokite API key can be provided via basic auth or in the request body.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"ApiKeyAuth":[]},{}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"basic","description":"Provide a Fotokite API key as a HTTP basic auth password (user name is ignored).\n"}},"schemas":{"TokenRequest":{"type":"object","description":"Request to obtain a session token. Compatible with OAuth2 `client_credentials` flow.","required":["client_secret"],"properties":{"grant_type":{"type":"string","description":"OAuth2 flow type, only \"client_credentials\" is supported.\n"},"client_id":{"type":"string","description":"Ignored (For OAuth compatibility)\n"},"client_secret":{"type":"string","description":"Fotokite API key. Contact Fotokite support to get an API key assigned and activated for your systems.\n"},"scope":{"type":"string","description":"Which scopes to request access for. This must be a subset of the scopes enabled for the plugin. If more scopes are requested, the request will fail. Space separated list.\n","allOf":[{"$ref":"#/components/schemas/Scopes"}]},"token_name":{"type":"string","description":"Name of the token for display to the operator if there can be multiple sessions per plugin.\n"}}},"Scopes":{"type":"string","description":"Available OAuth2 scopes:\n  * `read` - Grants access to retrieve system data and information.\n  * `control` - Allows sending commands to control the system.\n  * `can_override` - Allows to make `handoff/control/override` call to override current controlling client.\n  * `experimental` - Enables access to experimental API features.\n  * `internal` - Fotokite-internal functions. Not for third-party use.\n"},"Session":{"type":"object","description":"OAuth2 compatible access token response.","required":["id","plugin_id","scopes","access_token","created_at"],"properties":{"id":{"type":"string","description":"Unique ID of the session, used to identify the session in the system.\n"},"plugin_id":{"type":"string","description":"Unique ID of the plugin (API) key used to create this session.\n"},"plugin_name":{"type":"string","description":"Name of the plugin (API) key used to create this session.\n"},"scopes":{"type":"array","items":{"type":"string"},"description":"Scopes granted to this session token.\n"},"name":{"type":"string","description":"Name of the session for display to the operator.\n"},"valid_until":{"type":"string","format":"date-time","description":"Timestamp when this token expires and will no longer be valid.\n"},"created_at":{"type":"string","format":"date-time","description":"Timestamp when this token was created.\n"},"access_token":{"type":"string","description":"Token to use for future requests.\n"}}},"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}}},"paths":{"/v1/auth/token/request":{"post":{"tags":["Authentication"],"summary":"Request a token","description":"Initiate a request to obtain an authentication token for accessing protected API endpoints. In order to perform authenticated operations, you must first obtain a token by calling this endpoint. If the request is denied, Fotokite Live may prompt the operator for authorization, depending on system configuration. The Fotokite API key can be provided via basic auth or in the request body.\n","requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenRequest"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/TokenRequest"}}}},"responses":{"200":{"description":"Token issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Session"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden - API key valid but insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```

## Invalidate a token

> Invalidate the token used for calling the endpoint.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":[]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}}},"paths":{"/v1/auth/token/invalidate":{"post":{"tags":["Authentication"],"summary":"Invalidate a token","description":"Invalidate the token used for calling the endpoint.\n","responses":{"200":{"description":"Token invalidated"},"401":{"description":"Unauthorized - Invalid or missing API Token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden - Token valid but insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found - Specified session does not exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```

## Get active tokens

> Returns a list of active tokens<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"Session":{"type":"object","description":"OAuth2 compatible access token response.","required":["id","plugin_id","scopes","access_token","created_at"],"properties":{"id":{"type":"string","description":"Unique ID of the session, used to identify the session in the system.\n"},"plugin_id":{"type":"string","description":"Unique ID of the plugin (API) key used to create this session.\n"},"plugin_name":{"type":"string","description":"Name of the plugin (API) key used to create this session.\n"},"scopes":{"type":"array","items":{"type":"string"},"description":"Scopes granted to this session token.\n"},"name":{"type":"string","description":"Name of the session for display to the operator.\n"},"valid_until":{"type":"string","format":"date-time","description":"Timestamp when this token expires and will no longer be valid.\n"},"created_at":{"type":"string","format":"date-time","description":"Timestamp when this token was created.\n"},"access_token":{"type":"string","description":"Token to use for future requests.\n"}}},"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}},"responses":{"InternalError":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/auth/tokens":{"get":{"tags":["Authentication"],"summary":"Get active tokens","description":"Returns a list of active tokens\n","responses":{"200":{"description":"List of sessions","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Session"}}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden - API key valid but insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```

## Update plugin state<br>

> Update the state of a plugin<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"PluginSelfUpdatableFields":{"type":"object","description":"Updatable fields of the plugin to report self status.","properties":{"plugin_id":{"description":"**DEPRECATED: This field is still accepted for backward compatibility but will be removed in the future.**\n","deprecated":true,"type":"string"},"state":{"description":"**DEPRECATED: Use `self_status` instead. This field is still accepted for backward compatibility but will be removed in the future.** Possible values:\n  * `Disabled` - Operator has not enabled this plugin yet.\n  * `Enabled` - Operator has enabled the plugin, but there is no active session\n  * `Active` - There is at least one session using the plugin key.\n  * `Connected` - The plugin has reported that it is operational on any session.\n  * `Error` - The plugin has reported an error on any session.\n","deprecated":true,"type":"string"},"self_status":{"$ref":"#/components/schemas/PluginSelfStatus"},"self_status_text":{"$ref":"#/components/schemas/PluginStatusText"}}},"PluginSelfStatus":{"type":"string","description":"Status reported by the plugin code about itself.\n  * `None` or `<empty string>` - no additional information about the plugin status is available. This is the default status.\n  * `Connected` - the plugin is operational and connected to all required backend services.\n  * `Warning` - a situation that requires operator attention but is not critical occurred.\n  * `Error` - an error occurred and must be addressed by the operator.\n"},"PluginStatusText":{"type":"string","description":"Free-form status text reported by the plugin itself or by internal plugins. This is shown to the operator in the UI together with the state. There is no hard limit on the content of this field, but it is recommended to keep it concise and operator-friendly. Recommended max length is 160 characters. To reset the status text, send an empty string.\n"},"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}},"responses":{"InternalError":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/auth/plugin/update":{"post":{"tags":["Authentication"],"summary":"Update plugin state\n","description":"Update the state of a plugin\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PluginSelfUpdatableFields"}}}},"responses":{"204":{"description":"Updated"},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden - API key valid but insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found - Specified plugin does not exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid parameters - Request body or parameters are malformed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```


# Subscription

## Connect to web socket

> This endpoint will allow a connection upgrade to a websocket

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":[]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}}},"paths":{"/v1/{category}/{endpoint}/subscribe":{"get":{"tags":["Subscription"],"summary":"Connect to web socket","description":"This endpoint will allow a connection upgrade to a websocket","parameters":[{"in":"path","name":"category","description":"Category of the endpoint to subscribe to","required":true,"schema":{"type":"string"}},{"in":"path","name":"endpoint","description":"Which endpoint to subscribe to","required":true,"schema":{"type":"string"}}],"responses":{"101":{"description":"Websocket connection established.","headers":{"Set-Cookie":{"schema":{"type":"string"}}}},"404":{"description":"Endpoint does not exist"},"405":{"description":"Endpoint does not support subscription"}}}}}}
```

## POST /v1/{category}/{endpoint}/subscribe

> Subscribe for updates

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":[]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}}},"paths":{"/v1/{category}/{endpoint}/subscribe":{"post":{"tags":["Subscription"],"summary":"Subscribe for updates","parameters":[{"in":"path","name":"category","description":"Category of the endpoint to subscribe to","required":true,"schema":{"type":"string"}},{"in":"path","name":"endpoint","description":"Which endpoint to subscribe to","required":true,"schema":{"type":"string"}},{"in":"cookie","name":"connection","description":"Which connection to use","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Subscribed"},"400":{"description":"No such connection"},"404":{"description":"Endpoint does not exist"},"405":{"description":"Endpoint does not support subscription"}}}}}}
```


# Notifications

## Get system notifications

> Returns all current active notifications. Can be subscribed via a WebSocket connection.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"NotificationsObject":{"type":"object","description":"Notifications object","required":["notifications"],"properties":{"from_time":{"description":"The time from which notifications are sent (including the time point itself). In RFC3339 (section 5.6) format. This value typically comes from request query parameter. If request parameter is missed then only currently active notifications returned and `from_time` is missed. If too many notifications were requested then the value is set to the `end_time` of the first returned notification.\n","type":"string","format":"date-time"},"to_time":{"description":"Current system time up to which notifications were fetched (excluding the time point itself). In RFC3339 (section 5.6) format.","type":"string","format":"date-time"},"notifications":{"description":"Notifications array. If no notifications are registered in the time interval from `from_time` to `to_time` then the array is empty.","type":"array","items":{"$ref":"#/components/schemas/Notification"}}}},"Notification":{"type":"object","description":"One notification item","required":["severity","code","message","begin_time"],"properties":{"severity":{"$ref":"#/components/schemas/NotificationSeverity","description":"Notification severity"},"code":{"description":"Notification code. See the dictionary for all possible codes.","type":"integer"},"message":{"description":"Notification message. This is a human-readable message of the notification. It may contain parameters that are used in the notification texts.","type":"string"},"begin_time":{"description":"Notification begin time. This is the time point when the notification was initially detected. In RFC3339 (section 5.6) format.","type":"string","format":"date-time"},"end_time":{"description":"Notification end time. This is the time point when the notification was gone. In RFC3339 (section 5.6) format. If notification is still not gone then the property is absent.","type":"string","format":"date-time"},"parameters":{"description":"Notification parameters. This is a dictionary of key-value pairs that are used in the notification texts. The keys are defined in the notification code dictionary.\n","type":"object","additionalProperties":true}}},"NotificationSeverity":{"type":"string","description":"Notification severity enumeration.\n  * `Info` - Something happened that is not an issue, but may be of interest\n  * `Warning` - Something bad happened, but functionality is not affected\n  * `Critical` - Something bad happened, some functionality is broken\n  * `Fatal` - Something bad happened, system is not functional\n","enum":["Info","Warning","Critical","Fatal"]}}},"paths":{"/v1/notifications/state":{"get":{"tags":["Notifications"],"summary":"Get system notifications","description":"Returns all current active notifications. Can be subscribed via a WebSocket connection.\n","responses":{"200":{"description":"Success response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationsObject"}}}}}}}}}
```

## Get system notifications

> Returns system notifications. A notification is a temporary or permanent event that reflects the current system state. This could be an error state, an alert or a simple message. If the request parameter is empty, all currently active notifications will be returned. Every response contains \`to\_time\` time point. Up to this time point notifications are fetched. An event gets into the response, if the \`end\_time\` is not set or greater or equal to the \`to\_time\`. It is recommended to use this point for the next request to not miss any notification and to not request the same notifications multiple times.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"NotificationsObject":{"type":"object","description":"Notifications object","required":["notifications"],"properties":{"from_time":{"description":"The time from which notifications are sent (including the time point itself). In RFC3339 (section 5.6) format. This value typically comes from request query parameter. If request parameter is missed then only currently active notifications returned and `from_time` is missed. If too many notifications were requested then the value is set to the `end_time` of the first returned notification.\n","type":"string","format":"date-time"},"to_time":{"description":"Current system time up to which notifications were fetched (excluding the time point itself). In RFC3339 (section 5.6) format.","type":"string","format":"date-time"},"notifications":{"description":"Notifications array. If no notifications are registered in the time interval from `from_time` to `to_time` then the array is empty.","type":"array","items":{"$ref":"#/components/schemas/Notification"}}}},"Notification":{"type":"object","description":"One notification item","required":["severity","code","message","begin_time"],"properties":{"severity":{"$ref":"#/components/schemas/NotificationSeverity","description":"Notification severity"},"code":{"description":"Notification code. See the dictionary for all possible codes.","type":"integer"},"message":{"description":"Notification message. This is a human-readable message of the notification. It may contain parameters that are used in the notification texts.","type":"string"},"begin_time":{"description":"Notification begin time. This is the time point when the notification was initially detected. In RFC3339 (section 5.6) format.","type":"string","format":"date-time"},"end_time":{"description":"Notification end time. This is the time point when the notification was gone. In RFC3339 (section 5.6) format. If notification is still not gone then the property is absent.","type":"string","format":"date-time"},"parameters":{"description":"Notification parameters. This is a dictionary of key-value pairs that are used in the notification texts. The keys are defined in the notification code dictionary.\n","type":"object","additionalProperties":true}}},"NotificationSeverity":{"type":"string","description":"Notification severity enumeration.\n  * `Info` - Something happened that is not an issue, but may be of interest\n  * `Warning` - Something bad happened, but functionality is not affected\n  * `Critical` - Something bad happened, some functionality is broken\n  * `Fatal` - Something bad happened, system is not functional\n","enum":["Info","Warning","Critical","Fatal"]}}},"paths":{"/v1/notifications/history":{"get":{"tags":["Notifications"],"summary":"Get system notifications","description":"Returns system notifications. A notification is a temporary or permanent event that reflects the current system state. This could be an error state, an alert or a simple message. If the request parameter is empty, all currently active notifications will be returned. Every response contains `to_time` time point. Up to this time point notifications are fetched. An event gets into the response, if the `end_time` is not set or greater or equal to the `to_time`. It is recommended to use this point for the next request to not miss any notification and to not request the same notifications multiple times.\n","parameters":[{"name":"from_time","in":"query","required":false,"description":"The time from which notifications will be sent (including the time point itself). In RFC3339 (section 5.6) format. If this parameter is not set then only currently active notifications will be returned.\n","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Success response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationsObject"}}}}}}}}}
```

## Get notifications dictionary

> Returns the notifications dictionary. The dictionary contains all possible notifications that can be sent by the Fotokite system. It is recommended to use this endpoint to get the list of all possible notifications and their texts to display them to the user.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"NotificationDictionaryItem":{"type":"object","description":"Notification dictionary item object","required":["code","severity","message"],"properties":{"code":{"description":"Notification code","type":"integer"},"severity":{"$ref":"#/components/schemas/NotificationSeverity","description":"Notification severity"},"message":{"description":"Description message","type":"string"},"system_reaction":{"description":"System reaction message\n","type":"string"},"instructions":{"description":"User instructions message\n","type":"string"}}},"NotificationSeverity":{"type":"string","description":"Notification severity enumeration.\n  * `Info` - Something happened that is not an issue, but may be of interest\n  * `Warning` - Something bad happened, but functionality is not affected\n  * `Critical` - Something bad happened, some functionality is broken\n  * `Fatal` - Something bad happened, system is not functional\n","enum":["Info","Warning","Critical","Fatal"]}}},"paths":{"/v1/notifications/dictionary":{"get":{"tags":["Notifications"],"summary":"Get notifications dictionary","description":"Returns the notifications dictionary. The dictionary contains all possible notifications that can be sent by the Fotokite system. It is recommended to use this endpoint to get the list of all possible notifications and their texts to display them to the user.\n","responses":{"200":{"description":"Success response","content":{"application/json":{"schema":{"type":"array","description":"Notifications dictionary","items":{"$ref":"#/components/schemas/NotificationDictionaryItem"}}}}}}}}}}
```


# Handoff

## Get handoff control state

> Returns the current handoff control state, including which client (Fotokite Live, Fotokite API, or Plugin) currently controls the system and which clients have requested control. Subscribing to this endpoint is recommended to receive real-time updates.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"HandoffState":{"type":"object","description":"Information about connected and controlling entities.","required":["controlling_client","requesting_clients"],"properties":{"controlling_client":{"$ref":"#/components/schemas/ControllingClient","description":"Information about the entity currently controlling the system. If no entity is controlling the system, this field will be null.\n"},"requesting_clients":{"type":"array","items":{"$ref":"#/components/schemas/RequestingClient"}}}},"ControllingClient":{"nullable":true,"type":"object","description":"Information about controlling entity.","required":["session_id","operator_name"],"properties":{"plugin_id":{"type":"string","description":"Unique ID assigned by Fotokite assigned to this plugin.\n"},"plugin_name":{"type":"string","description":"Human readable name of the plugin. Has value of `Fotokite Live` for Fotokite Live application.\n"},"session_id":{"type":"string","description":"Unique ID of the session controlling control.\n"},"session_name":{"type":"string","description":"Name of the session for display to the operator if there can be multiple sessions per plugin.\n"},"operator_name":{"type":"string","description":"Operator name provided to `take_command` or `request_command` endpoint.\n"},"last_change":{"type":"string","format":"date-time","description":"Time when control was taken.\n"}}},"RequestingClient":{"type":"object","description":"Information about requested control client.","required":["session_id","operator_name"],"properties":{"plugin_id":{"type":"string","description":"Unique ID assigned by Fotokite assigned to this plugin.\n"},"plugin_name":{"type":"string","description":"Human readable name of the plugin. Has value of `Fotokite Live` for Fotokite Live application.\n"},"session_id":{"type":"string","description":"Unique ID of the session requested control.\n"},"session_name":{"type":"string","description":"Name of the session for display to the operator if there can be multiple sessions per plugin.\n"},"operator_name":{"type":"string","description":"Operator name provided to `take_command` or `request_command` endpoint.\n"},"last_change":{"type":"string","format":"date-time","description":"Time when the entity was added to the waiting queue.\n"}}}}},"paths":{"/v1/handoff/state":{"get":{"tags":["Handoff"],"summary":"Get handoff control state","description":"Returns the current handoff control state, including which client (Fotokite Live, Fotokite API, or Plugin) currently controls the system and which clients have requested control. Subscribing to this endpoint is recommended to receive real-time updates.\n","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HandoffState"}}}}}}}}}
```

## Request control

> Requests control of the Fotokite system. If no other client (Fotokite Live, Fotokite API, Plugin) is controlling, control is granted. If another client is controlling, the request is added to the waiting list (\`requesting\_clients\`) in \`handoff/state\`. A request remains valid for 1 minute; clients should periodically re-request control. The result of the request must be monitored using the \`handoff/state\` endpoint.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"RequestHandoffControl":{"type":"object","description":"Request to take control","required":["operator_name"],"properties":{"operator_name":{"type":"string","description":"Name of the operator taking control for display in UI.\n"},"regulatory_mode":{"$ref":"#/components/schemas/OperatorRegulatoryMode"},"operator_gps_lat":{"description":"Latitude of the operator reported by GPS [-90..+90] (degrees)","type":"number","minimum":-90,"exclusiveMinimum":true,"maximum":90},"operator_gps_lon":{"description":"Longitude of the operator reported by GPS (-180..+180] (degrees)","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"operator_gps_elevation":{"description":"Elevation of the operator reported by GPS (meters)","type":"number"},"operator_gps_accuracy":{"description":"Operator GPS accuracy in meters","type":"number","minimum":0}}},"OperatorRegulatoryMode":{"type":"string","description":"DroneID regulation variant that the UI provided to the operator complies with. DroneID broadcasts such as those required for FAA RemoteID contain information about the UAS operator. This endpoint can be used to provide such information. An update must be provided regularly according to the applicable regulation to prevent entering a DroneID error state (this may require sending handoff requests more frequently than it is required normally). By setting this value, you declare compliance with the relevant regulation. For the US:\n  * An operator location of sufficient accuracy is required. A GPS\n    receiver with SBAS augmentation is sufficient.\n  * Any DroneID error reported by the `/system/state` endpoint must cause\n    an audiovisual indicator to signal a Remote ID failure to the operator.\n\nPlease refer to FAA 14 CFR Part 89, ASTM F3411 and ASTM F3586 for details. **Possible values:**\n  * `US_REMOTE_ID_STANDARD`\n  * `unset`\nIf unset, this operator is not considered as a UAS operator, and a RemoteID error might occur if regulation requires an operator but no other operator is present. If no location information is provided, it is assumed that the operator is in direct vicinity of the Ground Station and the Ground Station location is used as the operator location.\n"},"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}},"responses":{"WrongInput":{"description":"Request parameter doesn't meet criteria","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/handoff/control/request":{"post":{"tags":["Handoff"],"summary":"Request control","description":"Requests control of the Fotokite system. If no other client (Fotokite Live, Fotokite API, Plugin) is controlling, control is granted. If another client is controlling, the request is added to the waiting list (`requesting_clients`) in `handoff/state`. A request remains valid for 1 minute; clients should periodically re-request control. The result of the request must be monitored using the `handoff/state` endpoint.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestHandoffControl"}}}},"responses":{"201":{"description":"Request to take control was accepted. This means that either the system is not controlled right now or the requestor already has control. Control will be revoked after 10 seconds. To prevent this, the requestor should periodically call `handoff/control/request`.\n"},"202":{"description":"Request was queued. This means that there is another entity controlling the system right now. The requestor should subscribe to the `handoff/state` endpoint or poll it to see the result of the request. It is also important to note that the request will be cleared after 1 minute if not taken.\n"},"400":{"$ref":"#/components/responses/WrongInput"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```

## Release control

> Releases control of the Fotokite system, allowing other clients (Fotokite Live, Fotokite API, or Plugin) to take control.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"responses":{"InternalError":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}}},"paths":{"/v1/handoff/control/release":{"post":{"tags":["Handoff"],"summary":"Release control","description":"Releases control of the Fotokite system, allowing other clients (Fotokite Live, Fotokite API, or Plugin) to take control.\n","responses":{"204":{"description":"Command was released successfully or requesting client successfully removed from the waiting queue or no one was controlling.\n"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```

## Override control

> Immediately enforces control of the Fotokite system, overriding other clients (Fotokite Live, Fotokite API, or Plugin) that may be blocking access. This endpoint is intended for use mainly by Fotokite Live.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control","can_override"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"RequestHandoffControl":{"type":"object","description":"Request to take control","required":["operator_name"],"properties":{"operator_name":{"type":"string","description":"Name of the operator taking control for display in UI.\n"},"regulatory_mode":{"$ref":"#/components/schemas/OperatorRegulatoryMode"},"operator_gps_lat":{"description":"Latitude of the operator reported by GPS [-90..+90] (degrees)","type":"number","minimum":-90,"exclusiveMinimum":true,"maximum":90},"operator_gps_lon":{"description":"Longitude of the operator reported by GPS (-180..+180] (degrees)","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"operator_gps_elevation":{"description":"Elevation of the operator reported by GPS (meters)","type":"number"},"operator_gps_accuracy":{"description":"Operator GPS accuracy in meters","type":"number","minimum":0}}},"OperatorRegulatoryMode":{"type":"string","description":"DroneID regulation variant that the UI provided to the operator complies with. DroneID broadcasts such as those required for FAA RemoteID contain information about the UAS operator. This endpoint can be used to provide such information. An update must be provided regularly according to the applicable regulation to prevent entering a DroneID error state (this may require sending handoff requests more frequently than it is required normally). By setting this value, you declare compliance with the relevant regulation. For the US:\n  * An operator location of sufficient accuracy is required. A GPS\n    receiver with SBAS augmentation is sufficient.\n  * Any DroneID error reported by the `/system/state` endpoint must cause\n    an audiovisual indicator to signal a Remote ID failure to the operator.\n\nPlease refer to FAA 14 CFR Part 89, ASTM F3411 and ASTM F3586 for details. **Possible values:**\n  * `US_REMOTE_ID_STANDARD`\n  * `unset`\nIf unset, this operator is not considered as a UAS operator, and a RemoteID error might occur if regulation requires an operator but no other operator is present. If no location information is provided, it is assumed that the operator is in direct vicinity of the Ground Station and the Ground Station location is used as the operator location.\n"},"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}},"responses":{"InternalError":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/handoff/control/override":{"post":{"tags":["Handoff"],"summary":"Override control","description":"Immediately enforces control of the Fotokite system, overriding other clients (Fotokite Live, Fotokite API, or Plugin) that may be blocking access. This endpoint is intended for use mainly by Fotokite Live.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestHandoffControl"}}}},"responses":{"201":{"description":"Success, command taken.\n"},"403":{"description":"Failure, current session can't command the system right now.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```


# System

## Get system information

> Returns system information.

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"SystemInfo":{"type":"object","description":"Represents system information","required":["gs_name","gs_mac","installation","model","timezone","timezone_name_short","timezone_offset","boards","software_channel","software_version"],"properties":{"gs_name":{"description":"Identity of the Ground Station","type":"string"},"gs_mac":{"description":"The MAC address of the router WAN port","type":"string"},"kite_name":{"description":"Name of the Kite","type":"string"},"rtb_name":{"description":"Name of the Rooftop Box (RTB)","type":"string"},"installation":{"description":"Type of installation. Possible values:\n  * `Transport Case`\n  * `Tray Mount`\n  * `Rooftop Box`\n  * `Dev Kit`\n  * `Bare Ground Station`\n","type":"string"},"model":{"description":"Model/generation of the Fotokite system","type":"string"},"propeller_model":{"description":"Model of the propellers used in the system. Possible values:\n  * `Propeller 1st Generation`\n  * `Propeller 2nd Generation`\n","type":"string"},"timezone":{"description":"Timezone of the Fotokite system","type":"string"},"timezone_name_short":{"description":"Short name of the timezone","type":"string"},"timezone_offset":{"description":"Offset of the timezone","type":"string"},"boards":{"type":"array","description":"List of system boards","items":{"$ref":"#/components/schemas/SystemBoard"}},"software_channel":{"type":"string","description":"System software channel"},"software_version":{"type":"string","description":"System software release version number"},"drone_id":{"$ref":"#/components/schemas/DroneIdInfo"}}},"SystemBoard":{"type":"object","description":"Represents a system board","required":["board","id"],"properties":{"board":{"type":"string","description":"Available system board names"},"id":{"description":"Unique identifier of a system board (e.g. \"001111211136511134311FFF\")\n","type":"string"}}},"DroneIdInfo":{"type":"object","description":"Static, system-level DroneID information.\n","required":["regulatory_mode","serial"],"properties":{"regulatory_mode":{"$ref":"#/components/schemas/RegulatoryMode"},"serial":{"type":"string","description":"ANSI/CTA-2063-A compliant serial number used for DroneID purposes"}}},"RegulatoryMode":{"type":"string","description":"DroneID regulation variant that the system needs to comply with. The possible values are:\n  * `DISABLED` - DroneID is disabled, no compliance provided.\n  * `US_REMOTE_ID_STANDARD` - The system is compliant with the US Remote ID Standard.\n  * `UNKNOWN` - Regulatory mode is unknown.\n"}}},"paths":{"/v1/system/info":{"get":{"tags":["System"],"summary":"Get system information","description":"Returns system information.","responses":{"200":{"description":"Success execution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemInfo"}}}}}}}}}
```

## Get system state

> Returns frequently changing system information.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"SystemState":{"type":"object","description":"Represents frequently changing system information\n","properties":{"kite_battery_level":{"description":"Kite backup battery charge level in percents [0..+100]","type":"number","minimum":0,"maximum":100},"gs_battery_level":{"description":"Ground Station backup battery charge level in percents [0..+100]","type":"number","minimum":0,"maximum":100},"gs_input_voltage":{"description":"Ground Station input voltage (volts)","type":"number"},"gs_gps_has_fix":{"description":"Whether the data reported by the Ground Station GPS is useable","type":"boolean"},"gs_gps_lat":{"description":"Latitude reported by Ground Station GPS [-90..+90] (degrees)","type":"number","minimum":-90,"exclusiveMinimum":true,"maximum":90},"gs_gps_lon":{"description":"Longitude reported by Ground Station GPS (-180..+180] (degrees)","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"gs_gps_elevation":{"description":"Elevation reported by Ground Station GPS (meters)","type":"number"},"gs_gps_accuracy":{"description":"Ground Station GPS accuracy in meters","type":"number","minimum":0},"drone_id":{"$ref":"#/components/schemas/DroneIdStatus"},"rtb_lids_state":{"$ref":"#/components/schemas/RTBLidsState"},"rtb_external_safety_land_button_state":{"description":"State of the external safety land button connected to the Rooftop Box","type":"string","enum":["Pressed","NotPressed"]},"rtb_parking_brake_state":{"description":"State of the parking brake on the Rooftop Box. When the parking brake is engaged, the system will not take off.","type":"string","enum":["Engaged","Disengaged"]}}},"DroneIdStatus":{"type":"object","description":"The current status of the system","required":["status","error_codes"],"properties":{"status":{"$ref":"#/components/schemas/DroneIdCheckStatus"},"error_codes":{"type":"array","items":{"$ref":"#/components/schemas/CurrentDroneIDErrorCode"},"description":"List of error codes that are currently applicable."}}},"DroneIdCheckStatus":{"type":"string","description":"Status of the DroneID check.\n  * `CHECKING` - The check is currently running.\n  * `OK` - The check completed successfully.\n  * `FAILED` - The check failed.\n  * `EMERGENCY` - The system is in an emergency state.\n"},"CurrentDroneIDErrorCode":{"description":"Code that describes what is wrong with DroneID. Values prefixed with `ERROR_` are hard errors that prevent the preflight check and cause DroneID to be non-compliant, while values prefixed with `WARNING_` indicate potential issues (data stale, no gps fix).\nThe non-compliant state should be indicated in the monitoring application.\nThe possible values are:\n  * `ERROR_UNKNOWN_REGULATORY_MODE` - Unknown regulatory mode (needs\n    config change or software update to fix).\n  * `ERROR_HARDWARE_VARIANT_UNSUITABLE` - Hardware variant and regulatory\n    mode configured are incompatible (needs hardware changes to fix).\n  * `ERROR_TX_FAILED` - Tx reports failure, maybe HW/SW defect (restart might fix it).\n  * `ERROR_TX_WRONG_WIFI_REGION` - Transmission is happening, but with the\n    wrong region settings (fix by changing wifi region).\n  * `ERROR_TX_WRONG_TRANSMISSION_POWER` - Transmission is happening, but\n    with higher or lower power than allowed (fix by changing wifi settings/region).\n  * `ERROR_TX_NOT_TRANSMITTING` - Tx(s) that should be transmitting, are\n    not (probably hardware malfunction if this persists).\n  * `ERROR_TX_TRANSMITTING` - At least one Tx is transmitting even though\n    it should not be (bug in tx software, try restarting).\n  * `ERROR_TX_STALE` - Tx is transmitting old data (might be intermittent).\n  * `ERROR_FW_INCOMPATIBLE` - The installed firmware doesn't support the\n    DroneID preflight check.\n  * `ERROR_NO_OPERATOR` - No operator connected that is compatible with DroneID.\n  * `ERROR_DATA_STALE` - We recently didn't receive required data (from\n    the kite, or, in the future, tablet). In this case we pretend that the\n    data is recent but put this alert here.\n  * `WARNING_DATA_INACCURATE` - No GPS fix, this is not a failure condition.\n","type":"string"},"RTBLidsState":{"type":"string","description":"Rooftop Box (RTB) lids state\n","enum":["Closed","Opening","Opened","Closing"]}}},"paths":{"/v1/system/state":{"get":{"tags":["System"],"summary":"Get system state","description":"Returns frequently changing system information.\n","responses":{"200":{"description":"Success execution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemState"}}}}}}}}}
```

## Open Rooftop Box lids

> Opens the Rooftop Box (RTB) lids. It is not necessary to call this endpoint before takeoff, as the system will automatically open the lids when needed. This endpoint is intended for maintenance purposes.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"responses":{"CommandSuccess":{"description":"The command was sent successfully"},"WrongSystemSetup":{"description":"The system is not set up to work as Rooftop Box, so the operation cannot be performed.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ControlCommandBlocked":{"description":"Control is not allowed because somebody else is controlling the System.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotAllowedInCurrentState":{"description":"The operation is not allowed in current state. Example: Rotation is not allowed during landing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServiceUnavailable":{"description":"The service is not ready yet. Usually this means that service didn't gather all the necessary information from subsystems.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}}},"paths":{"/v1/system/control/open_rtb_lids":{"post":{"tags":["System"],"summary":"Open Rooftop Box lids","description":"Opens the Rooftop Box (RTB) lids. It is not necessary to call this endpoint before takeoff, as the system will automatically open the lids when needed. This endpoint is intended for maintenance purposes.\n","responses":{"202":{"$ref":"#/components/responses/CommandSuccess"},"400":{"$ref":"#/components/responses/WrongSystemSetup"},"403":{"$ref":"#/components/responses/ControlCommandBlocked"},"409":{"$ref":"#/components/responses/NotAllowedInCurrentState"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}}}}
```

## Close Rooftop Box lids

> Closes the Rooftop Box (RTB) lids. It is not necessary to call this endpoint after landing, as the system will automatically close the lids when needed. This endpoint is intended for maintenance purposes.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"responses":{"CommandSuccess":{"description":"The command was sent successfully"},"WrongSystemSetup":{"description":"The system is not set up to work as Rooftop Box, so the operation cannot be performed.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ControlCommandBlocked":{"description":"Control is not allowed because somebody else is controlling the System.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotAllowedInCurrentState":{"description":"The operation is not allowed in current state. Example: Rotation is not allowed during landing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServiceUnavailable":{"description":"The service is not ready yet. Usually this means that service didn't gather all the necessary information from subsystems.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}}},"paths":{"/v1/system/control/close_rtb_lids":{"post":{"tags":["System"],"summary":"Close Rooftop Box lids","description":"Closes the Rooftop Box (RTB) lids. It is not necessary to call this endpoint after landing, as the system will automatically close the lids when needed. This endpoint is intended for maintenance purposes.\n","responses":{"202":{"$ref":"#/components/responses/CommandSuccess"},"400":{"$ref":"#/components/responses/WrongSystemSetup"},"403":{"$ref":"#/components/responses/ControlCommandBlocked"},"409":{"$ref":"#/components/responses/NotAllowedInCurrentState"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}}}}
```


# Flight

## Get flight information

> Returns flight information. Flight information contains properties that either do not change (ex. physical limitations) or change rarely (ex. legal restrictions).<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"FlightInfo":{"type":"object","description":"Flight information","required":["altitude_hard_max","altitude_soft_max"],"properties":{"altitude_takeoff":{"description":"Kite takeoff altitude (meters). The takeoff altitude is the altitude to which the Kite rises after takeoff. **Important: The Kite cannot fly lower than the takeoff altitude.**\n","type":"number"},"altitude_hard_max":{"description":"Maximum altitude (hard limit) of the Fotokite system (meters). Hard limit dictated by system capabilities or legal restrictions. The Kite cannot fly higher than this altitude.\n","type":"number"},"altitude_soft_max":{"description":"Maximum altitude (soft limit) of the Fotokite system (meters). This value can be set by an operator or API client to limit the maximum altitude of the Kite (ex. for safety reasons). This value resets on system reboot. The Kite cannot fly higher than this altitude.\n","type":"number"},"total_kite_flight_hours":{"description":"Total Kite flight time (hours). This value can be used for maintenance purposes. Note: initial value can be greater than 0 due to pre-delivery testing.\n","type":"number","minimum":0}}}}},"paths":{"/v1/flight/info":{"get":{"tags":["Flight"],"summary":"Get flight information","description":"Returns flight information. Flight information contains properties that either do not change (ex. physical limitations) or change rarely (ex. legal restrictions).\n","responses":{"200":{"description":"Success execution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlightInfo"}}}}}}}}}
```

## Get flight state

> Returns frequently changing flight information.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"FlightState":{"type":"object","description":"Represents frequently changing flight information. A property is not presented if it could not be gathered (for example due to a magnetometer or a GPS issue). Note: there is always a margin of error between the `altitude_target` and the altitude the Kite will take. And this error is not a constant.\n","required":["flight_state"],"properties":{"flight_state":{"$ref":"#/components/schemas/FlightStateEnum"},"altitude":{"description":"Current Kite altitude above the Ground Station (meters)","type":"number","minimum":0},"altitude_target":{"description":"Target Kite altitude set by the user (meters)","type":"number","minimum":0},"kite_heading":{"description":"Kite heading [0..+360) (degrees)","type":"number","minimum":0,"maximum":360,"exclusiveMaximum":true},"is_rotating":{"description":"Whether Kite is rotating (changing heading) (ex. as a result of the rotation command). True - Kite is rotating\n","type":"boolean"},"is_changing_altitude":{"description":"Whether Kite is changing altitude (ex. as a result of the set altitude command). True - Kite is changing altitude\n","type":"boolean"},"kite_gps_has_fix":{"description":"Whether the data reported by the Kite GPS is useable","type":"boolean"},"kite_gps_lat":{"description":"Latitude reported by Kite GPS [-90..+90] (degrees)","type":"number","minimum":-90,"maximum":90},"kite_gps_lon":{"description":"Longitude reported by Kite GPS (-180..+180] (degrees)","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"kite_gps_elevation":{"description":"Elevation reported by Kite GPS (meters)","type":"number"},"kite_gps_accuracy":{"description":"Kite GPS accuracy in meters","type":"number","minimum":0}}},"FlightStateEnum":{"type":"string","description":"Flight state enumeration\n  * `Unknown` - We couldn't get required data to conclude flight sate. This may happen due to numerous reasons:\n    Kite detached, Kite power is off, etc. More information can be found in notifications.\n  * `StandBy` - Kite is on the Ground Station\n  * `TakingOff` - Kite is doing preflight checks or taking off\n  * `Flying` - Kite is flying\n  * `Landing` - Kite is landing\n  * `SafetyLanding` - Kite is landing due to a critical issue happened during the flight.\n    More information can be found in notifications.\n  * `SafetyDescending` - Kite is descending for safety reasons (due to strong wind or weak GPS signal).\n    More information can be found in notifications.\n","enum":["Unknown","StandBy","TakingOff","Flying","Landing","SafetyLanding","SafetyDescending"]}}},"paths":{"/v1/flight/state":{"get":{"tags":["Flight"],"summary":"Get flight state","description":"Returns frequently changing flight information.\n","responses":{"200":{"description":"Success execution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlightState"}}}}}}}}}
```

## POST /v1/flight/control/take\_off

> Take off

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"responses":{"CommandSuccess":{"description":"The command was sent successfully"},"ControlCommandBlocked":{"description":"Control is not allowed because somebody else is controlling the System.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotAllowedInCurrentState":{"description":"The operation is not allowed in current state. Example: Rotation is not allowed during landing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}}},"paths":{"/v1/flight/control/take_off":{"post":{"tags":["Flight"],"summary":"Take off","responses":{"202":{"$ref":"#/components/responses/CommandSuccess"},"403":{"$ref":"#/components/responses/ControlCommandBlocked"},"409":{"$ref":"#/components/responses/NotAllowedInCurrentState"}}}}}}
```

## POST /v1/flight/control/land

> Land

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"responses":{"CommandSuccess":{"description":"The command was sent successfully"},"ControlCommandBlocked":{"description":"Control is not allowed because somebody else is controlling the System.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotAllowedInCurrentState":{"description":"The operation is not allowed in current state. Example: Rotation is not allowed during landing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}}},"paths":{"/v1/flight/control/land":{"post":{"tags":["Flight"],"summary":"Land","responses":{"202":{"$ref":"#/components/responses/CommandSuccess"},"403":{"$ref":"#/components/responses/ControlCommandBlocked"},"409":{"$ref":"#/components/responses/NotAllowedInCurrentState"}}}}}}
```

## POST /v1/flight/control/abort

> Abort take off, landing, or rotation command

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"responses":{"CommandSuccess":{"description":"The command was sent successfully"},"ControlCommandBlocked":{"description":"Control is not allowed because somebody else is controlling the System.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotAllowedInCurrentState":{"description":"The operation is not allowed in current state. Example: Rotation is not allowed during landing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}}},"paths":{"/v1/flight/control/abort":{"post":{"tags":["Flight"],"summary":"Abort take off, landing, or rotation command","responses":{"202":{"$ref":"#/components/responses/CommandSuccess"},"403":{"$ref":"#/components/responses/ControlCommandBlocked"},"409":{"$ref":"#/components/responses/NotAllowedInCurrentState"}}}}}}
```

## POST /v1/flight/control/altitude

> Set target altitude

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"ControlAltitudeRequest":{"type":"object","description":"Control altitude request data","required":["altitude"],"properties":{"altitude":{"description":"Sets target Kite altitude above the Ground Station (meters). Must not be lower than Kite takeoff altitude + 1 meter. But lower than both `altitude_hard_limit` and `altitude_soft_limit`. Note: there is always a margin of error between the `altitude_target` and the altitude the Kite will take. And this error is not a constant.\n","type":"number"}}},"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}},"responses":{"CommandSuccess":{"description":"The command was sent successfully"},"WrongInput":{"description":"Request parameter doesn't meet criteria","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ControlCommandBlocked":{"description":"Control is not allowed because somebody else is controlling the System.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotAllowedInCurrentState":{"description":"The operation is not allowed in current state. Example: Rotation is not allowed during landing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServiceUnavailable":{"description":"The service is not ready yet. Usually this means that service didn't gather all the necessary information from subsystems.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flight/control/altitude":{"post":{"tags":["Flight"],"summary":"Set target altitude","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ControlAltitudeRequest"}}}},"responses":{"202":{"$ref":"#/components/responses/CommandSuccess"},"400":{"$ref":"#/components/responses/WrongInput"},"403":{"$ref":"#/components/responses/ControlCommandBlocked"},"409":{"$ref":"#/components/responses/NotAllowedInCurrentState"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}}}}
```

## Set flight max altitude (soft limit)

> Sets or updates the Kite flight max altitude (soft limit). If the Kite is airborne at an altitude above the new soft limit, it will automatically descend to comply with the new limit. Note: this value resets on system reboot.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"ControlSoftAltitudeMaxRequest":{"type":"object","description":"Control altitude soft limit request data","required":["altitude"],"properties":{"altitude":{"description":"Maximum altitude (soft limit)\n","type":"number"}}},"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}},"responses":{"CommandSuccess":{"description":"The command was sent successfully"},"WrongInput":{"description":"Request parameter doesn't meet criteria","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ControlCommandBlocked":{"description":"Control is not allowed because somebody else is controlling the System.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServiceUnavailable":{"description":"The service is not ready yet. Usually this means that service didn't gather all the necessary information from subsystems.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flight/control/altitude_soft_max":{"post":{"tags":["Flight"],"summary":"Set flight max altitude (soft limit)","description":"Sets or updates the Kite flight max altitude (soft limit). If the Kite is airborne at an altitude above the new soft limit, it will automatically descend to comply with the new limit. Note: this value resets on system reboot.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ControlSoftAltitudeMaxRequest"}}}},"responses":{"204":{"$ref":"#/components/responses/CommandSuccess"},"400":{"$ref":"#/components/responses/WrongInput"},"403":{"$ref":"#/components/responses/ControlCommandBlocked"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}}}}
```


# Camera

## Get camera information

> Returns camera information.

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"CameraInfo":{"type":"object","description":"Camera information","properties":{"model":{"description":"Camera model. Allows to identify the camera type. Possible values:\n  * `Camera 1st Generation`. It has one color and one thermal module.\n  * `Camera 2nd Generation`. It has two color and one thermal module.\n    One color video stream has 32x zoom capabilities. Thermal module has resolution of 320x240.\n  * `Camera 2nd Generation IR Plus`. It has two color and one thermal module.\n    Thermal module is upgraded to a resolution of 640x512.\n","type":"string"},"pan_speed_min":{"description":"Minimum absolute pan speed of the camera (degrees/sec)","type":"number"},"pan_speed_max":{"description":"Maximum absolute pan speed of the camera (degrees/sec)","type":"number"},"tilt_speed_min":{"description":"Minimum absolute tilt speed of the camera (degrees/sec)","type":"number"},"tilt_speed_max":{"description":"Maximum absolute tilt speed of the camera (degrees/sec)","type":"number"},"tilt_min":{"description":"Minimum tilt angle of the camera relative to the kite (degrees)","type":"number","minimum":-90,"maximum":0},"tilt_max":{"description":"Maximum tilt angle of the camera relative to the kite (degrees)","type":"number","minimum":0,"maximum":90},"roll_min":{"description":"Minimum roll angle of the camera relative to the kite (degrees)","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":0},"roll_max":{"description":"Maximum roll angle of the camera relative to the kite (degrees)","type":"number","minimum":0,"maximum":180}}},"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}},"responses":{"CameraNotFound":{"description":"The operation requires a camera payload, but a different type of payload is currently installed. Please install a compatible camera payload to proceed.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/camera/info":{"get":{"tags":["Camera"],"summary":"Get camera information","description":"Returns camera information.","responses":{"200":{"description":"Camera information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CameraInfo"}}}},"404":{"$ref":"#/components/responses/CameraNotFound"}}}}}}
```

## Get camera state

> Returns camera frequently changing information.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"CameraState":{"type":"object","description":"Camera state","required":["online_state"],"properties":{"online_state":{"description":"If `Online` then the camera is powered on and can be used. This also means that the data about camera is up-to-date. If `Offline` then the camera is powered off or not connected to the system. In this case the data about the last online camera is provided. And this information may be inaccurate due to payload swap.\n","$ref":"#/components/schemas/OnlineState"},"pan_ned":{"description":"Camera pan angle in degrees in NED coordinates.\n  * 0 - The camera is looking North.\n  * +90 - The camera is looking East.\n  * +180 - The camera is looking South.\n  * -90 - The camera is looking West.\n","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"tilt_ned":{"description":"Camera tilt angle in degrees in NED coordinates.\n  * 0 - The camera is level, looking straight ahead.\n  * -90 - The camera is looking straight up.\n  * +90 - The camera is looking straight down towards gravity vector.\n","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"roll_ned":{"description":"Camera roll angle in degrees in NED coordinates.\n  * 0 - The camera is level, with the top facing upward.\n  * +90 - The top of the camera is rotated to the right.\n  * +180 - The top of the camera is facing downward (the same direction as gravity vector).\n  * -90 - The top of the camera is rotated to the left.\n","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180}}},"OnlineState":{"type":"string","description":"Online state of the payload.\n  * `Online` - payload is on and available to the system.\n  * `Offline` - payload is not available for some reason.\n","enum":["Online","Offline"]},"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}},"responses":{"CameraNotFound":{"description":"The operation requires a camera payload, but a different type of payload is currently installed. Please install a compatible camera payload to proceed.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/camera/state":{"get":{"tags":["Camera"],"summary":"Get camera state","description":"Returns camera frequently changing information.\n","responses":{"200":{"description":"Camera information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CameraState"}}}},"404":{"$ref":"#/components/responses/CameraNotFound"}}}}}}
```

## Rotate by angle

> Rotates the camera by a given angle. Optionally sets the tilt (applies only to the gimbal). For Fotokite Sigma, rotation is achieved through a combination of camera gimbal and kite movement.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"RotateCameraByAngle":{"type":"object","description":"Pan Kite and tilt camera by angle command arguments. If a property is missed then the Kite or camera will not be rotated in this direction.\n","properties":{"pan":{"description":"Change camera pan by this angle in degrees. Positive value means that the camera is rotated to the right.\n","type":"number","minimum":-180,"maximum":180},"tilt":{"description":"Change camera tilt by this angle in degrees. Positive value means that the camera is rotated down.\n","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180}}},"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}},"responses":{"CommandSuccess":{"description":"The command was sent successfully"},"WrongInput":{"description":"Request parameter doesn't meet criteria","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ControlCommandBlocked":{"description":"Control is not allowed because somebody else is controlling the System.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"CameraNotFound":{"description":"The operation requires a camera payload, but a different type of payload is currently installed. Please install a compatible camera payload to proceed.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotAllowedInCurrentState":{"description":"The operation is not allowed in current state. Example: Rotation is not allowed during landing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServiceUnavailable":{"description":"The service is not ready yet. Usually this means that service didn't gather all the necessary information from subsystems.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/camera/control/rotate_by_angle":{"post":{"tags":["Camera"],"summary":"Rotate by angle","description":"Rotates the camera by a given angle. Optionally sets the tilt (applies only to the gimbal). For Fotokite Sigma, rotation is achieved through a combination of camera gimbal and kite movement.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateCameraByAngle"}}}},"responses":{"202":{"$ref":"#/components/responses/CommandSuccess"},"400":{"$ref":"#/components/responses/WrongInput"},"403":{"$ref":"#/components/responses/ControlCommandBlocked"},"404":{"$ref":"#/components/responses/CameraNotFound"},"409":{"$ref":"#/components/responses/NotAllowedInCurrentState"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}}}}
```

## Rotate to angle

> Rotates the camera to a given angle. Optionally sets the tilt (applies only to the gimbal). For Fotokite Sigma, rotation is achieved through a combination of camera gimbal and kite movement.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"RotateCameraToAngle":{"type":"object","description":"Pan Kite and tilt camera to angle command arguments. If a property is missed then the Kite or camera will not be rotated in this direction.\n","properties":{"pan_ned":{"description":"Rotate the camera to the pan specified (in NED coordinates) [0..+360) (degrees). 0 - North, 90 - East, 180 - South, 270 - West.\n","type":"number","minimum":0,"maximum":360,"exclusiveMaximum":true},"tilt_ned":{"description":"Tilt (in NED coordinates) to rotate to in degrees.\n  * 0 - means that the camera is looking straight forward.\n  * -90 - means that the camera is looking straight up.\n  * +90 - means that the camera is looking straight down.\n  * +180 - means that the camera is looking backward and upside down.\n","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180}}},"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}},"responses":{"CommandSuccess":{"description":"The command was sent successfully"},"WrongInput":{"description":"Request parameter doesn't meet criteria","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ControlCommandBlocked":{"description":"Control is not allowed because somebody else is controlling the System.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"CameraNotFound":{"description":"The operation requires a camera payload, but a different type of payload is currently installed. Please install a compatible camera payload to proceed.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotAllowedInCurrentState":{"description":"The operation is not allowed in current state. Example: Rotation is not allowed during landing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServiceUnavailable":{"description":"The service is not ready yet. Usually this means that service didn't gather all the necessary information from subsystems.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/camera/control/rotate_to_angle":{"post":{"tags":["Camera"],"summary":"Rotate to angle","description":"Rotates the camera to a given angle. Optionally sets the tilt (applies only to the gimbal). For Fotokite Sigma, rotation is achieved through a combination of camera gimbal and kite movement.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateCameraToAngle"}}}},"responses":{"202":{"$ref":"#/components/responses/CommandSuccess"},"400":{"$ref":"#/components/responses/WrongInput"},"403":{"$ref":"#/components/responses/ControlCommandBlocked"},"404":{"$ref":"#/components/responses/CameraNotFound"},"409":{"$ref":"#/components/responses/NotAllowedInCurrentState"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}}}}
```

## Rotate with speed

> Rotates the camera at a given speed over a duration. To stop rotation immediately, set speed to 0. \*\*The Fotokite Sigma is not designed for constant unidirectional rotation, as this may twist and damage the tether cable. We recommend counteracting rotations (e.g., perform 10 rotations in one direction, then 10 in the opposite).\*\*<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"RotateCameraWithSpeed":{"type":"object","description":"Rotate camera with speed command data","required":["duration"],"properties":{"pan_speed":{"description":"Change the camera pan with the angle speed specified. Positive value - rotate clockwise (degrees/sec). Negative value - rotate counter-clockwise (degrees/sec). 0 - stop any previously commanded pan movement. If parameter missed then pan speed is considered to be 0 (no pan). Minimum absolute speed is `camera_pan_speed_min` (degrees/sec). Maximum absolute speed is `camera_pan_speed_max` (degrees/sec).\n","type":"number"},"tilt_speed":{"description":"Change the camera tilt with the angle speed specified. Positive value - rotate down (degrees/sec). Negative value - rotate up (degrees/sec). 0 - stop any previously commanded tilt movement. If parameter missed then tilt speed is considered to be 0 (no tilt). Minimum absolute speed is `camera_tilt_speed_min` (degrees/sec). Maximum absolute speed is `camera_tilt_speed_max` (degrees/sec).\n","type":"number"},"duration":{"description":"Duration of the command in seconds. The camera will rotate with the speed specified for the time specified.\n","type":"number","minimum":0.1,"maximum":10}}},"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}},"responses":{"CommandSuccess":{"description":"The command was sent successfully"},"WrongInput":{"description":"Request parameter doesn't meet criteria","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ControlCommandBlocked":{"description":"Control is not allowed because somebody else is controlling the System.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"CameraNotFound":{"description":"The operation requires a camera payload, but a different type of payload is currently installed. Please install a compatible camera payload to proceed.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotAllowedInCurrentState":{"description":"The operation is not allowed in current state. Example: Rotation is not allowed during landing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServiceUnavailable":{"description":"The service is not ready yet. Usually this means that service didn't gather all the necessary information from subsystems.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/camera/control/rotate_with_speed":{"post":{"tags":["Camera"],"summary":"Rotate with speed","description":"Rotates the camera at a given speed over a duration. To stop rotation immediately, set speed to 0. **The Fotokite Sigma is not designed for constant unidirectional rotation, as this may twist and damage the tether cable. We recommend counteracting rotations (e.g., perform 10 rotations in one direction, then 10 in the opposite).**\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateCameraWithSpeed"}}}},"responses":{"202":{"$ref":"#/components/responses/CommandSuccess"},"400":{"$ref":"#/components/responses/WrongInput"},"403":{"$ref":"#/components/responses/ControlCommandBlocked"},"404":{"$ref":"#/components/responses/CameraNotFound"},"409":{"$ref":"#/components/responses/NotAllowedInCurrentState"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}}}}
```


# Video Streams

## Get video streams information

> Returns video stream information. URLs for the video streams are generated dynamically based on client and network context, which prevents this endpoint from supporting subscriptions.<br>

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"VideoStreamInfo":{"type":"object","description":"Information about video stream. This information is mostly static but may change based on a user request.","required":["stream_id","type","codec","sensor_width","sensor_height","lens_focal_length","zoom_min","zoom_max","can_do_snapshot"],"properties":{"stream_id":{"description":"Unique video stream identifier.","type":"string"},"type":{"$ref":"#/components/schemas/VideoStreamType"},"frame_width":{"description":"Video frames width. Presented for fixed resolution encoders.","type":"integer"},"frame_height":{"description":"Video frames height. Presented for fixed resolution encoders.","type":"integer"},"sensor_width":{"description":"Sensor width in mm.","type":"number"},"sensor_height":{"description":"Sensor height in mm.","type":"number"},"lens_focal_length":{"description":"Lens focal length in mm. This value is constant and is not affected by zoom. This value corresponds to the `zoom_min` value.\n","type":"number"},"zoom_min":{"description":"Minimum zoom level.","type":"number"},"zoom_max":{"description":"Maximum zoom level.","type":"number"},"codec":{"description":"Video codec. Possible values:\n  * `H.264`\n","type":"string"},"rtsp_url":{"description":"RTSP video stream url.","type":"string"},"rtsps_url":{"description":"RTSPS encoded video stream url.","type":"string"},"can_do_snapshot":{"description":"If true then the video stream supports snapshot functionality. This means that the video stream can provide a snapshot image.\n","type":"boolean"}}},"VideoStreamType":{"type":"string","description":"Video stream type. Possible values:\n  * `Color` - regular color video stream.\n  * `Thermal` - thermal video stream.\n"}}},"paths":{"/v1/videostreams":{"get":{"tags":["Video streams"],"summary":"Get video streams information","description":"Returns video stream information. URLs for the video streams are generated dynamically based on client and network context, which prevents this endpoint from supporting subscriptions.\n","responses":{"200":{"description":"Video stream settings","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VideoStreamInfo"}}}}}}}}}}
```

## Get video stream state

> Returns frequently changing video stream information for the specified video stream.

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"VideoStreamState":{"type":"object","description":"Frequently changing information about video stream","required":["stream_id","is_streaming"],"properties":{"stream_id":{"description":"Unique video stream identifier.","type":"string"},"is_streaming":{"description":"If true then the video stream is currently streaming.\n","type":"boolean"},"timestamp":{"description":"Video timestamp of the last video frame. For RTP video streams this is the RTP timestamp.\n","type":"number"},"fov_horizontal":{"description":"Horizontal field of view in degrees.","type":"number"},"fov_vertical":{"description":"Vertical field of view in degrees.","type":"number"},"pan_ned":{"description":"Camera pan angle in degrees in NED coordinates.\n  * 0 - The camera is looking North.\n  * +90 - The camera is looking East.\n  * +180 - The camera is looking South.\n  * -90 - The camera is looking West.\n","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"tilt_ned":{"description":"Camera tilt angle in degrees in NED coordinates.\n  * 0 - The camera is level, looking straight ahead.\n  * -90 - The camera is looking straight up.\n  * +90 - The camera is looking straight down towards gravity vector.\n","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"roll_ned":{"description":"Camera roll angle in degrees in NED coordinates.\n  * 0 - The camera is level, with the top facing upward.\n  * +90 - The top of the camera is rotated to the right.\n  * +180 - The top of the camera is facing downward (the same direction as gravity vector).\n  * -90 - The top of the camera is rotated to the left.\n","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"zoom_level":{"description":"Current zoom level.","type":"number"},"thermal_color_palette":{"description":"Thermal color palette. This property is present only for thermal video streams. If the video stream is not thermal then this property is absent.\n","$ref":"#/components/schemas/ThermalColorPalette"}}},"ThermalColorPalette":{"type":"string","description":"Thermal color palette. Possible values:\n  * `WhiteHot`\n  * `BlackHot`\n  * `Rainbow`\n  * `RainbowHighContrast`\n  * `Ironbow`\n  * `Lava`\n  * `Arctic`\n  * `Glowbow`\n  * `GradedFire`\n  * `Hottest`\n"},"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}},"responses":{"VideostreamOrCameraNotFound":{"description":"The operation requires a camera payload, but either a different type of payload is currently installed, or the requested video stream does not exist for the installed camera.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/videostreams/{stream_id}/state":{"get":{"tags":["Video streams"],"summary":"Get video stream state","description":"Returns frequently changing video stream information for the specified video stream.","parameters":[{"in":"path","name":"stream_id","description":"Unique stream identifier.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Video stream frequently changing information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoStreamState"}}}},"404":{"$ref":"#/components/responses/VideostreamOrCameraNotFound"}}}}}}
```

## Set zoom

> Sets the zoom level for the specified video stream.

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"ControlZoomRequest":{"type":"object","description":"Request to set zoom level.","required":["zoom_level"],"properties":{"zoom_level":{"description":"New zoom level to set. Must be in the range from `zoom_min` to `zoom_max`.","type":"number"}}},"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}},"responses":{"CommandSuccess":{"description":"The command was sent successfully"},"WrongInput":{"description":"Request parameter doesn't meet criteria","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ControlCommandBlocked":{"description":"Control is not allowed because somebody else is controlling the System.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"VideostreamOrCameraNotFound":{"description":"The operation requires a camera payload, but either a different type of payload is currently installed, or the requested video stream does not exist for the installed camera.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotAllowedInCurrentState":{"description":"The operation is not allowed in current state. Example: Rotation is not allowed during landing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"BadGateway":{"description":"Bad Gateway. The service is not able to communicate with an upstream service it depends on.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServiceUnavailable":{"description":"The service is not ready yet. Usually this means that service didn't gather all the necessary information from subsystems.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/videostreams/{stream_id}/control/zoom":{"post":{"tags":["Video streams"],"summary":"Set zoom","description":"Sets the zoom level for the specified video stream.","parameters":[{"in":"path","name":"stream_id","description":"Unique stream identifier.","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ControlZoomRequest"}}}},"responses":{"202":{"$ref":"#/components/responses/CommandSuccess"},"400":{"$ref":"#/components/responses/WrongInput"},"403":{"$ref":"#/components/responses/ControlCommandBlocked"},"404":{"$ref":"#/components/responses/VideostreamOrCameraNotFound"},"409":{"$ref":"#/components/responses/NotAllowedInCurrentState"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}}}}
```

## Set thermal color palette

> Sets the thermal color palette for the specified video stream.

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"ControlThermalPaletteRequest":{"type":"object","description":"Request to set thermal color palette.","required":["thermal_color_palette"],"properties":{"thermal_color_palette":{"description":"New thermal color palette to set.","allOf":[{"$ref":"#/components/schemas/ThermalColorPalette"}]}}},"ThermalColorPalette":{"type":"string","description":"Thermal color palette. Possible values:\n  * `WhiteHot`\n  * `BlackHot`\n  * `Rainbow`\n  * `RainbowHighContrast`\n  * `Ironbow`\n  * `Lava`\n  * `Arctic`\n  * `Glowbow`\n  * `GradedFire`\n  * `Hottest`\n"},"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}},"responses":{"CommandSuccess":{"description":"The command was sent successfully"},"WrongInput":{"description":"Request parameter doesn't meet criteria","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ControlCommandBlocked":{"description":"Control is not allowed because somebody else is controlling the System.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"VideostreamOrCameraNotFound":{"description":"The operation requires a camera payload, but either a different type of payload is currently installed, or the requested video stream does not exist for the installed camera.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotAllowedInCurrentState":{"description":"The operation is not allowed in current state. Example: Rotation is not allowed during landing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"BadGateway":{"description":"Bad Gateway. The service is not able to communicate with an upstream service it depends on.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/videostreams/{stream_id}/control/palette":{"post":{"tags":["Video streams"],"summary":"Set thermal color palette","description":"Sets the thermal color palette for the specified video stream.","parameters":[{"in":"path","name":"stream_id","description":"Unique stream identifier.","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ControlThermalPaletteRequest"}}}},"responses":{"202":{"$ref":"#/components/responses/CommandSuccess"},"400":{"$ref":"#/components/responses/WrongInput"},"403":{"$ref":"#/components/responses/ControlCommandBlocked"},"404":{"$ref":"#/components/responses/VideostreamOrCameraNotFound"},"409":{"$ref":"#/components/responses/NotAllowedInCurrentState"},"502":{"$ref":"#/components/responses/BadGateway"}}}}}}
```

## Get snapshot

> Returns a snapshot from the specified video stream.

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"responses":{"WrongInput":{"description":"Request parameter doesn't meet criteria","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"VideostreamOrCameraNotFound":{"description":"The operation requires a camera payload, but either a different type of payload is currently installed, or the requested video stream does not exist for the installed camera.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotAllowedInCurrentState":{"description":"The operation is not allowed in current state. Example: Rotation is not allowed during landing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"BadGateway":{"description":"Bad Gateway. The service is not able to communicate with an upstream service it depends on.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}}},"paths":{"/v1/videostreams/{stream_id}/snapshot":{"get":{"tags":["Video streams"],"summary":"Get snapshot","description":"Returns a snapshot from the specified video stream.","parameters":[{"in":"path","name":"stream_id","description":"Unique stream identifier.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Snapshot image","content":{"image/jpeg":{"schema":{"type":"string","format":"binary"}}}},"400":{"$ref":"#/components/responses/WrongInput"},"404":{"$ref":"#/components/responses/VideostreamOrCameraNotFound"},"409":{"$ref":"#/components/responses/NotAllowedInCurrentState"},"502":{"$ref":"#/components/responses/BadGateway"}}}}}}
```


# Recordings

## Get video recordings

> A recording is a collection of video files (color and thermal) and metadata files.

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"Recording":{"type":"object","description":"Represents a video recording, including video files and metadata.","required":["recording_id","is_being_recorded","videos"],"properties":{"recording_id":{"type":"string","description":"Identifier of the recording."},"is_being_recorded":{"type":"boolean","description":"Whether this recording is currently being recorded."},"videos":{"type":"array","items":{"$ref":"#/components/schemas/VideoFile"}}}},"VideoFile":{"description":"Represents a video file in a recording, including metadata.","type":"object","required":["type","recording_id","file_id","size","is_recording"],"properties":{"type":{"$ref":"#/components/schemas/VideoStreamType"},"recording_id":{"type":"string","description":"ID of the video recording"},"file_id":{"type":"string","description":"Identifier of the video file. Used for downloading."},"size":{"type":"integer","format":"int64"},"is_recording":{"type":"boolean"}}},"VideoStreamType":{"type":"string","description":"Video stream type. Possible values:\n  * `Color` - regular color video stream.\n  * `Thermal` - thermal video stream.\n"}}},"paths":{"/v1/recordings":{"get":{"summary":"Get video recordings","description":"A recording is a collection of video files (color and thermal) and metadata files.","tags":["Recordings"],"responses":{"200":{"description":"List of video recordings","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Recording"}}}}}}}}}}
```

## Get video recorder state

> Returns the current video recorder state.

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"RecordingsState":{"type":"object","description":"Current state of the video recorder.","required":["available_space","total_space","is_recording"],"properties":{"recording_id":{"type":"string","description":"ID of the recording."},"started_recording_timestamp":{"type":"string","format":"date-time","description":"Last time a recording was started since boot, or zero otherwise."},"stopped_recording_timestamp":{"type":"string","format":"date-time","description":"Last time a recording was stopped, or current time if recording."},"is_recording":{"type":"boolean","description":"Whether the recorder is currently running."},"recording_seconds":{"type":"integer","format":"int32","description":"Number of seconds the current recording has been running."},"available_space":{"type":"integer","description":"Bytes available to store video recordings","format":"int64","minimum":0},"occupied_space":{"type":"integer","description":"Bytes currently occupied by video recordings","format":"int64","minimum":0},"total_space":{"type":"integer","description":"Total bytes available for video recordings","format":"int64","minimum":0}}}}},"paths":{"/v1/recordings/state":{"get":{"summary":"Get video recorder state","description":"Returns the current video recorder state.","tags":["Recordings"],"responses":{"200":{"description":"Current recorder state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordingsState"}}}}}}}}}
```

## Get video recording

> Returns a video recording. A video recording is a collection of video files (color and thermal) and metadata.

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"schemas":{"Recording":{"type":"object","description":"Represents a video recording, including video files and metadata.","required":["recording_id","is_being_recorded","videos"],"properties":{"recording_id":{"type":"string","description":"Identifier of the recording."},"is_being_recorded":{"type":"boolean","description":"Whether this recording is currently being recorded."},"videos":{"type":"array","items":{"$ref":"#/components/schemas/VideoFile"}}}},"VideoFile":{"description":"Represents a video file in a recording, including metadata.","type":"object","required":["type","recording_id","file_id","size","is_recording"],"properties":{"type":{"$ref":"#/components/schemas/VideoStreamType"},"recording_id":{"type":"string","description":"ID of the video recording"},"file_id":{"type":"string","description":"Identifier of the video file. Used for downloading."},"size":{"type":"integer","format":"int64"},"is_recording":{"type":"boolean"}}},"VideoStreamType":{"type":"string","description":"Video stream type. Possible values:\n  * `Color` - regular color video stream.\n  * `Thermal` - thermal video stream.\n"},"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}},"responses":{"NotFound":{"description":"File Not Found. Endpoint does not exist at all or the object referred to is not known.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/recordings/{recording_id}":{"get":{"summary":"Get video recording","description":"Returns a video recording. A video recording is a collection of video files (color and thermal) and metadata.","tags":["Recordings"],"responses":{"200":{"description":"Details of the video recording","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Recording"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## Delete video recording

> Deletes a video recording. A video recording is a collection of video files (color and thermal) and metadata.

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"responses":{"CommandSuccess":{"description":"The command was sent successfully"},"WrongInput":{"description":"Request parameter doesn't meet criteria","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"File Not Found. Endpoint does not exist at all or the object referred to is not known.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"BadGateway":{"description":"Bad Gateway. The service is not able to communicate with an upstream service it depends on.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServiceUnavailable":{"description":"The service is not ready yet. Usually this means that service didn't gather all the necessary information from subsystems.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}}},"paths":{"/v1/recordings/{recording_id}":{"delete":{"summary":"Delete video recording","description":"Deletes a video recording. A video recording is a collection of video files (color and thermal) and metadata.","tags":["Recordings"],"responses":{"200":{"$ref":"#/components/responses/CommandSuccess"},"400":{"$ref":"#/components/responses/WrongInput"},"404":{"$ref":"#/components/responses/NotFound"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}}}}
```

## Download video

> Returns a specific video of a recording.

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["read"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"responses":{"WrongInput":{"description":"Request parameter doesn't meet criteria","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"File Not Found. Endpoint does not exist at all or the object referred to is not known.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RangeNotSatisfiable":{"description":"Requested Range Not Satisfiable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"BadGateway":{"description":"Bad Gateway. The service is not able to communicate with an upstream service it depends on.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServiceUnavailable":{"description":"The service is not ready yet. Usually this means that service didn't gather all the necessary information from subsystems.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}}},"paths":{"/v1/recordings/{recording_id}/{file_id}":{"get":{"summary":"Download video","description":"Returns a specific video of a recording.","tags":["Recordings"],"responses":{"200":{"description":"Full file content","content":{"video/mp4":{"schema":{"type":"string","format":"binary"}},"image/jpeg":{"schema":{"type":"string","format":"binary"}}}},"206":{"description":"Partial file content","headers":{"Accept-Ranges":{"description":"The range unit supported by the server.","schema":{"type":"string"}},"Content-Length":{"description":"Length of the response body in bytes.","schema":{"type":"integer","format":"int64"}},"Content-Range":{"description":"Content byte range in the response.","schema":{"type":"string","pattern":"^bytes \\d+-\\d+/\\d+$"}}},"content":{"video/mp4":{"schema":{"type":"string","format":"binary"}}}},"400":{"$ref":"#/components/responses/WrongInput"},"404":{"$ref":"#/components/responses/NotFound"},"416":{"$ref":"#/components/responses/RangeNotSatisfiable"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}}}}
```

## Start video recording

> Starts a video recording. A video recording is a collection of video files (color and thermal) and metadata.

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"responses":{"CommandSuccess":{"description":"The command was sent successfully"},"WrongInput":{"description":"Request parameter doesn't meet criteria","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ControlCommandBlocked":{"description":"Control is not allowed because somebody else is controlling the System.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotAllowedInCurrentState":{"description":"The operation is not allowed in current state. Example: Rotation is not allowed during landing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"BadGateway":{"description":"Bad Gateway. The service is not able to communicate with an upstream service it depends on.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServiceUnavailable":{"description":"The service is not ready yet. Usually this means that service didn't gather all the necessary information from subsystems.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InsufficientStorage":{"description":"Insufficient Storage","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}}},"paths":{"/v1/recordings/control/start":{"post":{"summary":"Start video recording","description":"Starts a video recording. A video recording is a collection of video files (color and thermal) and metadata.","tags":["Recordings"],"responses":{"201":{"$ref":"#/components/responses/CommandSuccess"},"400":{"$ref":"#/components/responses/WrongInput"},"403":{"$ref":"#/components/responses/ControlCommandBlocked"},"409":{"$ref":"#/components/responses/NotAllowedInCurrentState"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/ServiceUnavailable"},"507":{"$ref":"#/components/responses/InsufficientStorage"}}}}}}
```

## Stop video recording

> Stops the current video recording.

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"servers":[{"url":"http://192.168.2.100:3128/api","description":"API service running on the system"},{"url":"http://{hostname_or_ip}/api","description":"Unencrypted API anywhere, for development use","variables":{"hostname_or_ip":{"default":"localhost:3128"}}},{"url":"https://{hostname_or_ip}/api","description":"Encrypted API accessible from outside the Sigma network","variables":{"hostname_or_ip":{"default":"fotokite-sigma.local"}}},{"url":"https://{gsname}.sigma.fotokite-system.com/api","description":"Hostname used for TLS certificates. The API is not reachable there, unless a local DNS override is set.","variables":{"gsname":{"default":"G2628RH"}}}],"security":[{"TokenAuth":["control"]}],"components":{"securitySchemes":{"TokenAuth":{"description":"Plugin authentication using Bearer token. For more details, see [Fotokite API Documentation](https://developer.fotokite.com/~/changes/46/getting-started#authentication).\n","type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"http://192.168.2.100:3128/api/v1/auth/token/request","scopes":{"read":"Grants access to retrieve system data and information.","control":"Allows sending commands to control the system.","can_override":"Allows to make `handoff/control/override` call to override current controlling client.","experimental":"Enables access to experimental API features.","internal":"Fotokite-internal functions. Not for third-party use."}}}}},"responses":{"CommandSuccess":{"description":"The command was sent successfully"},"WrongInput":{"description":"Request parameter doesn't meet criteria","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ControlCommandBlocked":{"description":"Control is not allowed because somebody else is controlling the System.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotAllowedInCurrentState":{"description":"The operation is not allowed in current state. Example: Rotation is not allowed during landing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"BadGateway":{"description":"Bad Gateway. The service is not able to communicate with an upstream service it depends on.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServiceUnavailable":{"description":"The service is not ready yet. Usually this means that service didn't gather all the necessary information from subsystems.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InsufficientStorage":{"description":"Insufficient Storage","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}}},"paths":{"/v1/recordings/control/stop":{"post":{"summary":"Stop video recording","description":"Stops the current video recording.","tags":["Recordings"],"responses":{"201":{"$ref":"#/components/responses/CommandSuccess"},"400":{"$ref":"#/components/responses/WrongInput"},"403":{"$ref":"#/components/responses/ControlCommandBlocked"},"409":{"$ref":"#/components/responses/NotAllowedInCurrentState"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/ServiceUnavailable"},"507":{"$ref":"#/components/responses/InsufficientStorage"}}}}}}
```


# Models

## The HealthResponse object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"HealthResponse":{"type":"object","description":"Health response","required":["status","api_version"],"properties":{"status":{"description":"Health status","type":"string"},"api_version":{"description":"SemVer version of the Fotokite API.","type":"string"}}}}}}
```

## The Error object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"Error":{"type":"object","description":"A generic error object.","required":["code","message"],"properties":{"code":{"description":"Unique error code.","type":"string"},"message":{"description":"User readable message of the error","type":"string"}}}}}}
```

## The OnlineState object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"OnlineState":{"type":"string","description":"Online state of the payload.\n  * `Online` - payload is on and available to the system.\n  * `Offline` - payload is not available for some reason.\n","enum":["Online","Offline"]}}}}
```

## The Scopes object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"Scopes":{"type":"string","description":"Available OAuth2 scopes:\n  * `read` - Grants access to retrieve system data and information.\n  * `control` - Allows sending commands to control the system.\n  * `can_override` - Allows to make `handoff/control/override` call to override current controlling client.\n  * `experimental` - Enables access to experimental API features.\n  * `internal` - Fotokite-internal functions. Not for third-party use.\n"}}}}
```

## The TokenRequest object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"TokenRequest":{"type":"object","description":"Request to obtain a session token. Compatible with OAuth2 `client_credentials` flow.","required":["client_secret"],"properties":{"grant_type":{"type":"string","description":"OAuth2 flow type, only \"client_credentials\" is supported.\n"},"client_id":{"type":"string","description":"Ignored (For OAuth compatibility)\n"},"client_secret":{"type":"string","description":"Fotokite API key. Contact Fotokite support to get an API key assigned and activated for your systems.\n"},"scope":{"type":"string","description":"Which scopes to request access for. This must be a subset of the scopes enabled for the plugin. If more scopes are requested, the request will fail. Space separated list.\n","allOf":[{"$ref":"#/components/schemas/Scopes"}]},"token_name":{"type":"string","description":"Name of the token for display to the operator if there can be multiple sessions per plugin.\n"}}},"Scopes":{"type":"string","description":"Available OAuth2 scopes:\n  * `read` - Grants access to retrieve system data and information.\n  * `control` - Allows sending commands to control the system.\n  * `can_override` - Allows to make `handoff/control/override` call to override current controlling client.\n  * `experimental` - Enables access to experimental API features.\n  * `internal` - Fotokite-internal functions. Not for third-party use.\n"}}}}
```

## The Session object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"Session":{"type":"object","description":"OAuth2 compatible access token response.","required":["id","plugin_id","scopes","access_token","created_at"],"properties":{"id":{"type":"string","description":"Unique ID of the session, used to identify the session in the system.\n"},"plugin_id":{"type":"string","description":"Unique ID of the plugin (API) key used to create this session.\n"},"plugin_name":{"type":"string","description":"Name of the plugin (API) key used to create this session.\n"},"scopes":{"type":"array","items":{"type":"string"},"description":"Scopes granted to this session token.\n"},"name":{"type":"string","description":"Name of the session for display to the operator.\n"},"valid_until":{"type":"string","format":"date-time","description":"Timestamp when this token expires and will no longer be valid.\n"},"created_at":{"type":"string","format":"date-time","description":"Timestamp when this token was created.\n"},"access_token":{"type":"string","description":"Token to use for future requests.\n"}}}}}}
```

## The PluginSelfUpdatableFields object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"PluginSelfUpdatableFields":{"type":"object","description":"Updatable fields of the plugin to report self status.","properties":{"plugin_id":{"description":"**DEPRECATED: This field is still accepted for backward compatibility but will be removed in the future.**\n","deprecated":true,"type":"string"},"state":{"description":"**DEPRECATED: Use `self_status` instead. This field is still accepted for backward compatibility but will be removed in the future.** Possible values:\n  * `Disabled` - Operator has not enabled this plugin yet.\n  * `Enabled` - Operator has enabled the plugin, but there is no active session\n  * `Active` - There is at least one session using the plugin key.\n  * `Connected` - The plugin has reported that it is operational on any session.\n  * `Error` - The plugin has reported an error on any session.\n","deprecated":true,"type":"string"},"self_status":{"$ref":"#/components/schemas/PluginSelfStatus"},"self_status_text":{"$ref":"#/components/schemas/PluginStatusText"}}},"PluginSelfStatus":{"type":"string","description":"Status reported by the plugin code about itself.\n  * `None` or `<empty string>` - no additional information about the plugin status is available. This is the default status.\n  * `Connected` - the plugin is operational and connected to all required backend services.\n  * `Warning` - a situation that requires operator attention but is not critical occurred.\n  * `Error` - an error occurred and must be addressed by the operator.\n"},"PluginStatusText":{"type":"string","description":"Free-form status text reported by the plugin itself or by internal plugins. This is shown to the operator in the UI together with the state. There is no hard limit on the content of this field, but it is recommended to keep it concise and operator-friendly. Recommended max length is 160 characters. To reset the status text, send an empty string.\n"}}}}
```

## The PluginSupervisoryUpdatableFields object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"PluginSupervisoryUpdatableFields":{"type":"object","description":"Updatable fields of a plugin. Can be used by other internal plugins to report status of a plugin. If you don't want to change a plugin aspect - just don't include the corresponding field in the request.\n","properties":{"is_enabled":{"type":"boolean","description":"Request to enable or disable the plugin. This is used by Fotokite Live.\n"},"state":{"description":"**DEPRECATED: Use `supervisory_status` instead. This field is still accepted for backward compatibility but will be removed in the future.** Possible values:\n  * `Disabled` - Operator has not enabled this plugin yet.\n  * `Enabled` - Operator has enabled the plugin, but there is no active session\n  * `Active` - There is at least one session using the plugin key.\n  * `Connected` - The plugin has reported that it is operational on any session.\n  * `Error` - The plugin has reported an error on any session.\n","deprecated":true,"type":"string"},"supervisory_status":{"$ref":"#/components/schemas/PluginSupervisoryStatus"},"supervisory_status_text":{"$ref":"#/components/schemas/PluginStatusText"}}},"PluginSupervisoryStatus":{"type":"string","description":"Status reported by an internal plugin about another plugin.\n  * `None` or `<empty string>` - no additional information about the plugin status is available. This is the default status.\n  * `Downloading` - plugin loader is downloading the plugin (if applicable).\n  * `Warning` - a situation that requires operator attention but is not critical occurred.\n  * `Error` - an error occurred and must be addressed by the operator.\n"},"PluginStatusText":{"type":"string","description":"Free-form status text reported by the plugin itself or by internal plugins. This is shown to the operator in the UI together with the state. There is no hard limit on the content of this field, but it is recommended to keep it concise and operator-friendly. Recommended max length is 160 characters. To reset the status text, send an empty string.\n"}}}}
```

## The ApiKey object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"ApiKey":{"type":"object","description":"Hashed Fotokite API key used by this plugin","required":["key"],"properties":{"key":{"type":"string","description":"Hashed key\n"},"valid_from":{"type":"string"}}}}}}
```

## The PluginSelfStatus object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"PluginSelfStatus":{"type":"string","description":"Status reported by the plugin code about itself.\n  * `None` or `<empty string>` - no additional information about the plugin status is available. This is the default status.\n  * `Connected` - the plugin is operational and connected to all required backend services.\n  * `Warning` - a situation that requires operator attention but is not critical occurred.\n  * `Error` - an error occurred and must be addressed by the operator.\n"}}}}
```

## The PluginSupervisoryStatus object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"PluginSupervisoryStatus":{"type":"string","description":"Status reported by an internal plugin about another plugin.\n  * `None` or `<empty string>` - no additional information about the plugin status is available. This is the default status.\n  * `Downloading` - plugin loader is downloading the plugin (if applicable).\n  * `Warning` - a situation that requires operator attention but is not critical occurred.\n  * `Error` - an error occurred and must be addressed by the operator.\n"}}}}
```

## The PluginStatusText object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"PluginStatusText":{"type":"string","description":"Free-form status text reported by the plugin itself or by internal plugins. This is shown to the operator in the UI together with the state. There is no hard limit on the content of this field, but it is recommended to keep it concise and operator-friendly. Recommended max length is 160 characters. To reset the status text, send an empty string.\n"}}}}
```

## The NotificationDictionaryItem object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"NotificationDictionaryItem":{"type":"object","description":"Notification dictionary item object","required":["code","severity","message"],"properties":{"code":{"description":"Notification code","type":"integer"},"severity":{"$ref":"#/components/schemas/NotificationSeverity","description":"Notification severity"},"message":{"description":"Description message","type":"string"},"system_reaction":{"description":"System reaction message\n","type":"string"},"instructions":{"description":"User instructions message\n","type":"string"}}},"NotificationSeverity":{"type":"string","description":"Notification severity enumeration.\n  * `Info` - Something happened that is not an issue, but may be of interest\n  * `Warning` - Something bad happened, but functionality is not affected\n  * `Critical` - Something bad happened, some functionality is broken\n  * `Fatal` - Something bad happened, system is not functional\n","enum":["Info","Warning","Critical","Fatal"]}}}}
```

## The NotificationsObject object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"NotificationsObject":{"type":"object","description":"Notifications object","required":["notifications"],"properties":{"from_time":{"description":"The time from which notifications are sent (including the time point itself). In RFC3339 (section 5.6) format. This value typically comes from request query parameter. If request parameter is missed then only currently active notifications returned and `from_time` is missed. If too many notifications were requested then the value is set to the `end_time` of the first returned notification.\n","type":"string","format":"date-time"},"to_time":{"description":"Current system time up to which notifications were fetched (excluding the time point itself). In RFC3339 (section 5.6) format.","type":"string","format":"date-time"},"notifications":{"description":"Notifications array. If no notifications are registered in the time interval from `from_time` to `to_time` then the array is empty.","type":"array","items":{"$ref":"#/components/schemas/Notification"}}}},"Notification":{"type":"object","description":"One notification item","required":["severity","code","message","begin_time"],"properties":{"severity":{"$ref":"#/components/schemas/NotificationSeverity","description":"Notification severity"},"code":{"description":"Notification code. See the dictionary for all possible codes.","type":"integer"},"message":{"description":"Notification message. This is a human-readable message of the notification. It may contain parameters that are used in the notification texts.","type":"string"},"begin_time":{"description":"Notification begin time. This is the time point when the notification was initially detected. In RFC3339 (section 5.6) format.","type":"string","format":"date-time"},"end_time":{"description":"Notification end time. This is the time point when the notification was gone. In RFC3339 (section 5.6) format. If notification is still not gone then the property is absent.","type":"string","format":"date-time"},"parameters":{"description":"Notification parameters. This is a dictionary of key-value pairs that are used in the notification texts. The keys are defined in the notification code dictionary.\n","type":"object","additionalProperties":true}}},"NotificationSeverity":{"type":"string","description":"Notification severity enumeration.\n  * `Info` - Something happened that is not an issue, but may be of interest\n  * `Warning` - Something bad happened, but functionality is not affected\n  * `Critical` - Something bad happened, some functionality is broken\n  * `Fatal` - Something bad happened, system is not functional\n","enum":["Info","Warning","Critical","Fatal"]}}}}
```

## The Notification object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"Notification":{"type":"object","description":"One notification item","required":["severity","code","message","begin_time"],"properties":{"severity":{"$ref":"#/components/schemas/NotificationSeverity","description":"Notification severity"},"code":{"description":"Notification code. See the dictionary for all possible codes.","type":"integer"},"message":{"description":"Notification message. This is a human-readable message of the notification. It may contain parameters that are used in the notification texts.","type":"string"},"begin_time":{"description":"Notification begin time. This is the time point when the notification was initially detected. In RFC3339 (section 5.6) format.","type":"string","format":"date-time"},"end_time":{"description":"Notification end time. This is the time point when the notification was gone. In RFC3339 (section 5.6) format. If notification is still not gone then the property is absent.","type":"string","format":"date-time"},"parameters":{"description":"Notification parameters. This is a dictionary of key-value pairs that are used in the notification texts. The keys are defined in the notification code dictionary.\n","type":"object","additionalProperties":true}}},"NotificationSeverity":{"type":"string","description":"Notification severity enumeration.\n  * `Info` - Something happened that is not an issue, but may be of interest\n  * `Warning` - Something bad happened, but functionality is not affected\n  * `Critical` - Something bad happened, some functionality is broken\n  * `Fatal` - Something bad happened, system is not functional\n","enum":["Info","Warning","Critical","Fatal"]}}}}
```

## The NotificationSeverity object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"NotificationSeverity":{"type":"string","description":"Notification severity enumeration.\n  * `Info` - Something happened that is not an issue, but may be of interest\n  * `Warning` - Something bad happened, but functionality is not affected\n  * `Critical` - Something bad happened, some functionality is broken\n  * `Fatal` - Something bad happened, system is not functional\n","enum":["Info","Warning","Critical","Fatal"]}}}}
```

## The HandoffState object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"HandoffState":{"type":"object","description":"Information about connected and controlling entities.","required":["controlling_client","requesting_clients"],"properties":{"controlling_client":{"$ref":"#/components/schemas/ControllingClient","description":"Information about the entity currently controlling the system. If no entity is controlling the system, this field will be null.\n"},"requesting_clients":{"type":"array","items":{"$ref":"#/components/schemas/RequestingClient"}}}},"ControllingClient":{"nullable":true,"type":"object","description":"Information about controlling entity.","required":["session_id","operator_name"],"properties":{"plugin_id":{"type":"string","description":"Unique ID assigned by Fotokite assigned to this plugin.\n"},"plugin_name":{"type":"string","description":"Human readable name of the plugin. Has value of `Fotokite Live` for Fotokite Live application.\n"},"session_id":{"type":"string","description":"Unique ID of the session controlling control.\n"},"session_name":{"type":"string","description":"Name of the session for display to the operator if there can be multiple sessions per plugin.\n"},"operator_name":{"type":"string","description":"Operator name provided to `take_command` or `request_command` endpoint.\n"},"last_change":{"type":"string","format":"date-time","description":"Time when control was taken.\n"}}},"RequestingClient":{"type":"object","description":"Information about requested control client.","required":["session_id","operator_name"],"properties":{"plugin_id":{"type":"string","description":"Unique ID assigned by Fotokite assigned to this plugin.\n"},"plugin_name":{"type":"string","description":"Human readable name of the plugin. Has value of `Fotokite Live` for Fotokite Live application.\n"},"session_id":{"type":"string","description":"Unique ID of the session requested control.\n"},"session_name":{"type":"string","description":"Name of the session for display to the operator if there can be multiple sessions per plugin.\n"},"operator_name":{"type":"string","description":"Operator name provided to `take_command` or `request_command` endpoint.\n"},"last_change":{"type":"string","format":"date-time","description":"Time when the entity was added to the waiting queue.\n"}}}}}}
```

## The ControllingClient object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"ControllingClient":{"nullable":true,"type":"object","description":"Information about controlling entity.","required":["session_id","operator_name"],"properties":{"plugin_id":{"type":"string","description":"Unique ID assigned by Fotokite assigned to this plugin.\n"},"plugin_name":{"type":"string","description":"Human readable name of the plugin. Has value of `Fotokite Live` for Fotokite Live application.\n"},"session_id":{"type":"string","description":"Unique ID of the session controlling control.\n"},"session_name":{"type":"string","description":"Name of the session for display to the operator if there can be multiple sessions per plugin.\n"},"operator_name":{"type":"string","description":"Operator name provided to `take_command` or `request_command` endpoint.\n"},"last_change":{"type":"string","format":"date-time","description":"Time when control was taken.\n"}}}}}}
```

## The RequestingClient object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"RequestingClient":{"type":"object","description":"Information about requested control client.","required":["session_id","operator_name"],"properties":{"plugin_id":{"type":"string","description":"Unique ID assigned by Fotokite assigned to this plugin.\n"},"plugin_name":{"type":"string","description":"Human readable name of the plugin. Has value of `Fotokite Live` for Fotokite Live application.\n"},"session_id":{"type":"string","description":"Unique ID of the session requested control.\n"},"session_name":{"type":"string","description":"Name of the session for display to the operator if there can be multiple sessions per plugin.\n"},"operator_name":{"type":"string","description":"Operator name provided to `take_command` or `request_command` endpoint.\n"},"last_change":{"type":"string","format":"date-time","description":"Time when the entity was added to the waiting queue.\n"}}}}}}
```

## The RequestHandoffControl object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"RequestHandoffControl":{"type":"object","description":"Request to take control","required":["operator_name"],"properties":{"operator_name":{"type":"string","description":"Name of the operator taking control for display in UI.\n"},"regulatory_mode":{"$ref":"#/components/schemas/OperatorRegulatoryMode"},"operator_gps_lat":{"description":"Latitude of the operator reported by GPS [-90..+90] (degrees)","type":"number","minimum":-90,"exclusiveMinimum":true,"maximum":90},"operator_gps_lon":{"description":"Longitude of the operator reported by GPS (-180..+180] (degrees)","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"operator_gps_elevation":{"description":"Elevation of the operator reported by GPS (meters)","type":"number"},"operator_gps_accuracy":{"description":"Operator GPS accuracy in meters","type":"number","minimum":0}}},"OperatorRegulatoryMode":{"type":"string","description":"DroneID regulation variant that the UI provided to the operator complies with. DroneID broadcasts such as those required for FAA RemoteID contain information about the UAS operator. This endpoint can be used to provide such information. An update must be provided regularly according to the applicable regulation to prevent entering a DroneID error state (this may require sending handoff requests more frequently than it is required normally). By setting this value, you declare compliance with the relevant regulation. For the US:\n  * An operator location of sufficient accuracy is required. A GPS\n    receiver with SBAS augmentation is sufficient.\n  * Any DroneID error reported by the `/system/state` endpoint must cause\n    an audiovisual indicator to signal a Remote ID failure to the operator.\n\nPlease refer to FAA 14 CFR Part 89, ASTM F3411 and ASTM F3586 for details. **Possible values:**\n  * `US_REMOTE_ID_STANDARD`\n  * `unset`\nIf unset, this operator is not considered as a UAS operator, and a RemoteID error might occur if regulation requires an operator but no other operator is present. If no location information is provided, it is assumed that the operator is in direct vicinity of the Ground Station and the Ground Station location is used as the operator location.\n"}}}}
```

## The OperatorRegulatoryMode object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"OperatorRegulatoryMode":{"type":"string","description":"DroneID regulation variant that the UI provided to the operator complies with. DroneID broadcasts such as those required for FAA RemoteID contain information about the UAS operator. This endpoint can be used to provide such information. An update must be provided regularly according to the applicable regulation to prevent entering a DroneID error state (this may require sending handoff requests more frequently than it is required normally). By setting this value, you declare compliance with the relevant regulation. For the US:\n  * An operator location of sufficient accuracy is required. A GPS\n    receiver with SBAS augmentation is sufficient.\n  * Any DroneID error reported by the `/system/state` endpoint must cause\n    an audiovisual indicator to signal a Remote ID failure to the operator.\n\nPlease refer to FAA 14 CFR Part 89, ASTM F3411 and ASTM F3586 for details. **Possible values:**\n  * `US_REMOTE_ID_STANDARD`\n  * `unset`\nIf unset, this operator is not considered as a UAS operator, and a RemoteID error might occur if regulation requires an operator but no other operator is present. If no location information is provided, it is assumed that the operator is in direct vicinity of the Ground Station and the Ground Station location is used as the operator location.\n"}}}}
```

## The SystemInfo object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"SystemInfo":{"type":"object","description":"Represents system information","required":["gs_name","gs_mac","installation","model","timezone","timezone_name_short","timezone_offset","boards","software_channel","software_version"],"properties":{"gs_name":{"description":"Identity of the Ground Station","type":"string"},"gs_mac":{"description":"The MAC address of the router WAN port","type":"string"},"kite_name":{"description":"Name of the Kite","type":"string"},"rtb_name":{"description":"Name of the Rooftop Box (RTB)","type":"string"},"installation":{"description":"Type of installation. Possible values:\n  * `Transport Case`\n  * `Tray Mount`\n  * `Rooftop Box`\n  * `Dev Kit`\n  * `Bare Ground Station`\n","type":"string"},"model":{"description":"Model/generation of the Fotokite system","type":"string"},"propeller_model":{"description":"Model of the propellers used in the system. Possible values:\n  * `Propeller 1st Generation`\n  * `Propeller 2nd Generation`\n","type":"string"},"timezone":{"description":"Timezone of the Fotokite system","type":"string"},"timezone_name_short":{"description":"Short name of the timezone","type":"string"},"timezone_offset":{"description":"Offset of the timezone","type":"string"},"boards":{"type":"array","description":"List of system boards","items":{"$ref":"#/components/schemas/SystemBoard"}},"software_channel":{"type":"string","description":"System software channel"},"software_version":{"type":"string","description":"System software release version number"},"drone_id":{"$ref":"#/components/schemas/DroneIdInfo"}}},"SystemBoard":{"type":"object","description":"Represents a system board","required":["board","id"],"properties":{"board":{"type":"string","description":"Available system board names"},"id":{"description":"Unique identifier of a system board (e.g. \"001111211136511134311FFF\")\n","type":"string"}}},"DroneIdInfo":{"type":"object","description":"Static, system-level DroneID information.\n","required":["regulatory_mode","serial"],"properties":{"regulatory_mode":{"$ref":"#/components/schemas/RegulatoryMode"},"serial":{"type":"string","description":"ANSI/CTA-2063-A compliant serial number used for DroneID purposes"}}},"RegulatoryMode":{"type":"string","description":"DroneID regulation variant that the system needs to comply with. The possible values are:\n  * `DISABLED` - DroneID is disabled, no compliance provided.\n  * `US_REMOTE_ID_STANDARD` - The system is compliant with the US Remote ID Standard.\n  * `UNKNOWN` - Regulatory mode is unknown.\n"}}}}
```

## The SystemBoard object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"SystemBoard":{"type":"object","description":"Represents a system board","required":["board","id"],"properties":{"board":{"type":"string","description":"Available system board names"},"id":{"description":"Unique identifier of a system board (e.g. \"001111211136511134311FFF\")\n","type":"string"}}}}}}
```

## The SystemState object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"SystemState":{"type":"object","description":"Represents frequently changing system information\n","properties":{"kite_battery_level":{"description":"Kite backup battery charge level in percents [0..+100]","type":"number","minimum":0,"maximum":100},"gs_battery_level":{"description":"Ground Station backup battery charge level in percents [0..+100]","type":"number","minimum":0,"maximum":100},"gs_input_voltage":{"description":"Ground Station input voltage (volts)","type":"number"},"gs_gps_has_fix":{"description":"Whether the data reported by the Ground Station GPS is useable","type":"boolean"},"gs_gps_lat":{"description":"Latitude reported by Ground Station GPS [-90..+90] (degrees)","type":"number","minimum":-90,"exclusiveMinimum":true,"maximum":90},"gs_gps_lon":{"description":"Longitude reported by Ground Station GPS (-180..+180] (degrees)","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"gs_gps_elevation":{"description":"Elevation reported by Ground Station GPS (meters)","type":"number"},"gs_gps_accuracy":{"description":"Ground Station GPS accuracy in meters","type":"number","minimum":0},"drone_id":{"$ref":"#/components/schemas/DroneIdStatus"},"rtb_lids_state":{"$ref":"#/components/schemas/RTBLidsState"},"rtb_external_safety_land_button_state":{"description":"State of the external safety land button connected to the Rooftop Box","type":"string","enum":["Pressed","NotPressed"]},"rtb_parking_brake_state":{"description":"State of the parking brake on the Rooftop Box. When the parking brake is engaged, the system will not take off.","type":"string","enum":["Engaged","Disengaged"]}}},"DroneIdStatus":{"type":"object","description":"The current status of the system","required":["status","error_codes"],"properties":{"status":{"$ref":"#/components/schemas/DroneIdCheckStatus"},"error_codes":{"type":"array","items":{"$ref":"#/components/schemas/CurrentDroneIDErrorCode"},"description":"List of error codes that are currently applicable."}}},"DroneIdCheckStatus":{"type":"string","description":"Status of the DroneID check.\n  * `CHECKING` - The check is currently running.\n  * `OK` - The check completed successfully.\n  * `FAILED` - The check failed.\n  * `EMERGENCY` - The system is in an emergency state.\n"},"CurrentDroneIDErrorCode":{"description":"Code that describes what is wrong with DroneID. Values prefixed with `ERROR_` are hard errors that prevent the preflight check and cause DroneID to be non-compliant, while values prefixed with `WARNING_` indicate potential issues (data stale, no gps fix).\nThe non-compliant state should be indicated in the monitoring application.\nThe possible values are:\n  * `ERROR_UNKNOWN_REGULATORY_MODE` - Unknown regulatory mode (needs\n    config change or software update to fix).\n  * `ERROR_HARDWARE_VARIANT_UNSUITABLE` - Hardware variant and regulatory\n    mode configured are incompatible (needs hardware changes to fix).\n  * `ERROR_TX_FAILED` - Tx reports failure, maybe HW/SW defect (restart might fix it).\n  * `ERROR_TX_WRONG_WIFI_REGION` - Transmission is happening, but with the\n    wrong region settings (fix by changing wifi region).\n  * `ERROR_TX_WRONG_TRANSMISSION_POWER` - Transmission is happening, but\n    with higher or lower power than allowed (fix by changing wifi settings/region).\n  * `ERROR_TX_NOT_TRANSMITTING` - Tx(s) that should be transmitting, are\n    not (probably hardware malfunction if this persists).\n  * `ERROR_TX_TRANSMITTING` - At least one Tx is transmitting even though\n    it should not be (bug in tx software, try restarting).\n  * `ERROR_TX_STALE` - Tx is transmitting old data (might be intermittent).\n  * `ERROR_FW_INCOMPATIBLE` - The installed firmware doesn't support the\n    DroneID preflight check.\n  * `ERROR_NO_OPERATOR` - No operator connected that is compatible with DroneID.\n  * `ERROR_DATA_STALE` - We recently didn't receive required data (from\n    the kite, or, in the future, tablet). In this case we pretend that the\n    data is recent but put this alert here.\n  * `WARNING_DATA_INACCURATE` - No GPS fix, this is not a failure condition.\n","type":"string"},"RTBLidsState":{"type":"string","description":"Rooftop Box (RTB) lids state\n","enum":["Closed","Opening","Opened","Closing"]}}}}
```

## The RTBLidsState object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"RTBLidsState":{"type":"string","description":"Rooftop Box (RTB) lids state\n","enum":["Closed","Opening","Opened","Closing"]}}}}
```

## The DroneIdInfo object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"DroneIdInfo":{"type":"object","description":"Static, system-level DroneID information.\n","required":["regulatory_mode","serial"],"properties":{"regulatory_mode":{"$ref":"#/components/schemas/RegulatoryMode"},"serial":{"type":"string","description":"ANSI/CTA-2063-A compliant serial number used for DroneID purposes"}}},"RegulatoryMode":{"type":"string","description":"DroneID regulation variant that the system needs to comply with. The possible values are:\n  * `DISABLED` - DroneID is disabled, no compliance provided.\n  * `US_REMOTE_ID_STANDARD` - The system is compliant with the US Remote ID Standard.\n  * `UNKNOWN` - Regulatory mode is unknown.\n"}}}}
```

## The DroneIdStatus object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"DroneIdStatus":{"type":"object","description":"The current status of the system","required":["status","error_codes"],"properties":{"status":{"$ref":"#/components/schemas/DroneIdCheckStatus"},"error_codes":{"type":"array","items":{"$ref":"#/components/schemas/CurrentDroneIDErrorCode"},"description":"List of error codes that are currently applicable."}}},"DroneIdCheckStatus":{"type":"string","description":"Status of the DroneID check.\n  * `CHECKING` - The check is currently running.\n  * `OK` - The check completed successfully.\n  * `FAILED` - The check failed.\n  * `EMERGENCY` - The system is in an emergency state.\n"},"CurrentDroneIDErrorCode":{"description":"Code that describes what is wrong with DroneID. Values prefixed with `ERROR_` are hard errors that prevent the preflight check and cause DroneID to be non-compliant, while values prefixed with `WARNING_` indicate potential issues (data stale, no gps fix).\nThe non-compliant state should be indicated in the monitoring application.\nThe possible values are:\n  * `ERROR_UNKNOWN_REGULATORY_MODE` - Unknown regulatory mode (needs\n    config change or software update to fix).\n  * `ERROR_HARDWARE_VARIANT_UNSUITABLE` - Hardware variant and regulatory\n    mode configured are incompatible (needs hardware changes to fix).\n  * `ERROR_TX_FAILED` - Tx reports failure, maybe HW/SW defect (restart might fix it).\n  * `ERROR_TX_WRONG_WIFI_REGION` - Transmission is happening, but with the\n    wrong region settings (fix by changing wifi region).\n  * `ERROR_TX_WRONG_TRANSMISSION_POWER` - Transmission is happening, but\n    with higher or lower power than allowed (fix by changing wifi settings/region).\n  * `ERROR_TX_NOT_TRANSMITTING` - Tx(s) that should be transmitting, are\n    not (probably hardware malfunction if this persists).\n  * `ERROR_TX_TRANSMITTING` - At least one Tx is transmitting even though\n    it should not be (bug in tx software, try restarting).\n  * `ERROR_TX_STALE` - Tx is transmitting old data (might be intermittent).\n  * `ERROR_FW_INCOMPATIBLE` - The installed firmware doesn't support the\n    DroneID preflight check.\n  * `ERROR_NO_OPERATOR` - No operator connected that is compatible with DroneID.\n  * `ERROR_DATA_STALE` - We recently didn't receive required data (from\n    the kite, or, in the future, tablet). In this case we pretend that the\n    data is recent but put this alert here.\n  * `WARNING_DATA_INACCURATE` - No GPS fix, this is not a failure condition.\n","type":"string"}}}}
```

## The RegulatoryMode object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"RegulatoryMode":{"type":"string","description":"DroneID regulation variant that the system needs to comply with. The possible values are:\n  * `DISABLED` - DroneID is disabled, no compliance provided.\n  * `US_REMOTE_ID_STANDARD` - The system is compliant with the US Remote ID Standard.\n  * `UNKNOWN` - Regulatory mode is unknown.\n"}}}}
```

## The CurrentDroneIDErrorCode object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"CurrentDroneIDErrorCode":{"description":"Code that describes what is wrong with DroneID. Values prefixed with `ERROR_` are hard errors that prevent the preflight check and cause DroneID to be non-compliant, while values prefixed with `WARNING_` indicate potential issues (data stale, no gps fix).\nThe non-compliant state should be indicated in the monitoring application.\nThe possible values are:\n  * `ERROR_UNKNOWN_REGULATORY_MODE` - Unknown regulatory mode (needs\n    config change or software update to fix).\n  * `ERROR_HARDWARE_VARIANT_UNSUITABLE` - Hardware variant and regulatory\n    mode configured are incompatible (needs hardware changes to fix).\n  * `ERROR_TX_FAILED` - Tx reports failure, maybe HW/SW defect (restart might fix it).\n  * `ERROR_TX_WRONG_WIFI_REGION` - Transmission is happening, but with the\n    wrong region settings (fix by changing wifi region).\n  * `ERROR_TX_WRONG_TRANSMISSION_POWER` - Transmission is happening, but\n    with higher or lower power than allowed (fix by changing wifi settings/region).\n  * `ERROR_TX_NOT_TRANSMITTING` - Tx(s) that should be transmitting, are\n    not (probably hardware malfunction if this persists).\n  * `ERROR_TX_TRANSMITTING` - At least one Tx is transmitting even though\n    it should not be (bug in tx software, try restarting).\n  * `ERROR_TX_STALE` - Tx is transmitting old data (might be intermittent).\n  * `ERROR_FW_INCOMPATIBLE` - The installed firmware doesn't support the\n    DroneID preflight check.\n  * `ERROR_NO_OPERATOR` - No operator connected that is compatible with DroneID.\n  * `ERROR_DATA_STALE` - We recently didn't receive required data (from\n    the kite, or, in the future, tablet). In this case we pretend that the\n    data is recent but put this alert here.\n  * `WARNING_DATA_INACCURATE` - No GPS fix, this is not a failure condition.\n","type":"string"}}}}
```

## The DroneIdCheckStatus object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"DroneIdCheckStatus":{"type":"string","description":"Status of the DroneID check.\n  * `CHECKING` - The check is currently running.\n  * `OK` - The check completed successfully.\n  * `FAILED` - The check failed.\n  * `EMERGENCY` - The system is in an emergency state.\n"}}}}
```

## The FlightInfo object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"FlightInfo":{"type":"object","description":"Flight information","required":["altitude_hard_max","altitude_soft_max"],"properties":{"altitude_takeoff":{"description":"Kite takeoff altitude (meters). The takeoff altitude is the altitude to which the Kite rises after takeoff. **Important: The Kite cannot fly lower than the takeoff altitude.**\n","type":"number"},"altitude_hard_max":{"description":"Maximum altitude (hard limit) of the Fotokite system (meters). Hard limit dictated by system capabilities or legal restrictions. The Kite cannot fly higher than this altitude.\n","type":"number"},"altitude_soft_max":{"description":"Maximum altitude (soft limit) of the Fotokite system (meters). This value can be set by an operator or API client to limit the maximum altitude of the Kite (ex. for safety reasons). This value resets on system reboot. The Kite cannot fly higher than this altitude.\n","type":"number"},"total_kite_flight_hours":{"description":"Total Kite flight time (hours). This value can be used for maintenance purposes. Note: initial value can be greater than 0 due to pre-delivery testing.\n","type":"number","minimum":0}}}}}}
```

## The FlightState object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"FlightState":{"type":"object","description":"Represents frequently changing flight information. A property is not presented if it could not be gathered (for example due to a magnetometer or a GPS issue). Note: there is always a margin of error between the `altitude_target` and the altitude the Kite will take. And this error is not a constant.\n","required":["flight_state"],"properties":{"flight_state":{"$ref":"#/components/schemas/FlightStateEnum"},"altitude":{"description":"Current Kite altitude above the Ground Station (meters)","type":"number","minimum":0},"altitude_target":{"description":"Target Kite altitude set by the user (meters)","type":"number","minimum":0},"kite_heading":{"description":"Kite heading [0..+360) (degrees)","type":"number","minimum":0,"maximum":360,"exclusiveMaximum":true},"is_rotating":{"description":"Whether Kite is rotating (changing heading) (ex. as a result of the rotation command). True - Kite is rotating\n","type":"boolean"},"is_changing_altitude":{"description":"Whether Kite is changing altitude (ex. as a result of the set altitude command). True - Kite is changing altitude\n","type":"boolean"},"kite_gps_has_fix":{"description":"Whether the data reported by the Kite GPS is useable","type":"boolean"},"kite_gps_lat":{"description":"Latitude reported by Kite GPS [-90..+90] (degrees)","type":"number","minimum":-90,"maximum":90},"kite_gps_lon":{"description":"Longitude reported by Kite GPS (-180..+180] (degrees)","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"kite_gps_elevation":{"description":"Elevation reported by Kite GPS (meters)","type":"number"},"kite_gps_accuracy":{"description":"Kite GPS accuracy in meters","type":"number","minimum":0}}},"FlightStateEnum":{"type":"string","description":"Flight state enumeration\n  * `Unknown` - We couldn't get required data to conclude flight sate. This may happen due to numerous reasons:\n    Kite detached, Kite power is off, etc. More information can be found in notifications.\n  * `StandBy` - Kite is on the Ground Station\n  * `TakingOff` - Kite is doing preflight checks or taking off\n  * `Flying` - Kite is flying\n  * `Landing` - Kite is landing\n  * `SafetyLanding` - Kite is landing due to a critical issue happened during the flight.\n    More information can be found in notifications.\n  * `SafetyDescending` - Kite is descending for safety reasons (due to strong wind or weak GPS signal).\n    More information can be found in notifications.\n","enum":["Unknown","StandBy","TakingOff","Flying","Landing","SafetyLanding","SafetyDescending"]}}}}
```

## The FlightStateEnum object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"FlightStateEnum":{"type":"string","description":"Flight state enumeration\n  * `Unknown` - We couldn't get required data to conclude flight sate. This may happen due to numerous reasons:\n    Kite detached, Kite power is off, etc. More information can be found in notifications.\n  * `StandBy` - Kite is on the Ground Station\n  * `TakingOff` - Kite is doing preflight checks or taking off\n  * `Flying` - Kite is flying\n  * `Landing` - Kite is landing\n  * `SafetyLanding` - Kite is landing due to a critical issue happened during the flight.\n    More information can be found in notifications.\n  * `SafetyDescending` - Kite is descending for safety reasons (due to strong wind or weak GPS signal).\n    More information can be found in notifications.\n","enum":["Unknown","StandBy","TakingOff","Flying","Landing","SafetyLanding","SafetyDescending"]}}}}
```

## The ControlAltitudeRequest object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"ControlAltitudeRequest":{"type":"object","description":"Control altitude request data","required":["altitude"],"properties":{"altitude":{"description":"Sets target Kite altitude above the Ground Station (meters). Must not be lower than Kite takeoff altitude + 1 meter. But lower than both `altitude_hard_limit` and `altitude_soft_limit`. Note: there is always a margin of error between the `altitude_target` and the altitude the Kite will take. And this error is not a constant.\n","type":"number"}}}}}}
```

## The ControlSoftAltitudeMaxRequest object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"ControlSoftAltitudeMaxRequest":{"type":"object","description":"Control altitude soft limit request data","required":["altitude"],"properties":{"altitude":{"description":"Maximum altitude (soft limit)\n","type":"number"}}}}}}
```

## The CameraInfo object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"CameraInfo":{"type":"object","description":"Camera information","properties":{"model":{"description":"Camera model. Allows to identify the camera type. Possible values:\n  * `Camera 1st Generation`. It has one color and one thermal module.\n  * `Camera 2nd Generation`. It has two color and one thermal module.\n    One color video stream has 32x zoom capabilities. Thermal module has resolution of 320x240.\n  * `Camera 2nd Generation IR Plus`. It has two color and one thermal module.\n    Thermal module is upgraded to a resolution of 640x512.\n","type":"string"},"pan_speed_min":{"description":"Minimum absolute pan speed of the camera (degrees/sec)","type":"number"},"pan_speed_max":{"description":"Maximum absolute pan speed of the camera (degrees/sec)","type":"number"},"tilt_speed_min":{"description":"Minimum absolute tilt speed of the camera (degrees/sec)","type":"number"},"tilt_speed_max":{"description":"Maximum absolute tilt speed of the camera (degrees/sec)","type":"number"},"tilt_min":{"description":"Minimum tilt angle of the camera relative to the kite (degrees)","type":"number","minimum":-90,"maximum":0},"tilt_max":{"description":"Maximum tilt angle of the camera relative to the kite (degrees)","type":"number","minimum":0,"maximum":90},"roll_min":{"description":"Minimum roll angle of the camera relative to the kite (degrees)","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":0},"roll_max":{"description":"Maximum roll angle of the camera relative to the kite (degrees)","type":"number","minimum":0,"maximum":180}}}}}}
```

## The CameraState object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"CameraState":{"type":"object","description":"Camera state","required":["online_state"],"properties":{"online_state":{"description":"If `Online` then the camera is powered on and can be used. This also means that the data about camera is up-to-date. If `Offline` then the camera is powered off or not connected to the system. In this case the data about the last online camera is provided. And this information may be inaccurate due to payload swap.\n","$ref":"#/components/schemas/OnlineState"},"pan_ned":{"description":"Camera pan angle in degrees in NED coordinates.\n  * 0 - The camera is looking North.\n  * +90 - The camera is looking East.\n  * +180 - The camera is looking South.\n  * -90 - The camera is looking West.\n","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"tilt_ned":{"description":"Camera tilt angle in degrees in NED coordinates.\n  * 0 - The camera is level, looking straight ahead.\n  * -90 - The camera is looking straight up.\n  * +90 - The camera is looking straight down towards gravity vector.\n","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"roll_ned":{"description":"Camera roll angle in degrees in NED coordinates.\n  * 0 - The camera is level, with the top facing upward.\n  * +90 - The top of the camera is rotated to the right.\n  * +180 - The top of the camera is facing downward (the same direction as gravity vector).\n  * -90 - The top of the camera is rotated to the left.\n","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180}}},"OnlineState":{"type":"string","description":"Online state of the payload.\n  * `Online` - payload is on and available to the system.\n  * `Offline` - payload is not available for some reason.\n","enum":["Online","Offline"]}}}}
```

## The RotateCameraByAngle object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"RotateCameraByAngle":{"type":"object","description":"Pan Kite and tilt camera by angle command arguments. If a property is missed then the Kite or camera will not be rotated in this direction.\n","properties":{"pan":{"description":"Change camera pan by this angle in degrees. Positive value means that the camera is rotated to the right.\n","type":"number","minimum":-180,"maximum":180},"tilt":{"description":"Change camera tilt by this angle in degrees. Positive value means that the camera is rotated down.\n","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180}}}}}}
```

## The RotateCameraToAngle object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"RotateCameraToAngle":{"type":"object","description":"Pan Kite and tilt camera to angle command arguments. If a property is missed then the Kite or camera will not be rotated in this direction.\n","properties":{"pan_ned":{"description":"Rotate the camera to the pan specified (in NED coordinates) [0..+360) (degrees). 0 - North, 90 - East, 180 - South, 270 - West.\n","type":"number","minimum":0,"maximum":360,"exclusiveMaximum":true},"tilt_ned":{"description":"Tilt (in NED coordinates) to rotate to in degrees.\n  * 0 - means that the camera is looking straight forward.\n  * -90 - means that the camera is looking straight up.\n  * +90 - means that the camera is looking straight down.\n  * +180 - means that the camera is looking backward and upside down.\n","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180}}}}}}
```

## The RotateCameraWithSpeed object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"RotateCameraWithSpeed":{"type":"object","description":"Rotate camera with speed command data","required":["duration"],"properties":{"pan_speed":{"description":"Change the camera pan with the angle speed specified. Positive value - rotate clockwise (degrees/sec). Negative value - rotate counter-clockwise (degrees/sec). 0 - stop any previously commanded pan movement. If parameter missed then pan speed is considered to be 0 (no pan). Minimum absolute speed is `camera_pan_speed_min` (degrees/sec). Maximum absolute speed is `camera_pan_speed_max` (degrees/sec).\n","type":"number"},"tilt_speed":{"description":"Change the camera tilt with the angle speed specified. Positive value - rotate down (degrees/sec). Negative value - rotate up (degrees/sec). 0 - stop any previously commanded tilt movement. If parameter missed then tilt speed is considered to be 0 (no tilt). Minimum absolute speed is `camera_tilt_speed_min` (degrees/sec). Maximum absolute speed is `camera_tilt_speed_max` (degrees/sec).\n","type":"number"},"duration":{"description":"Duration of the command in seconds. The camera will rotate with the speed specified for the time specified.\n","type":"number","minimum":0.1,"maximum":10}}}}}}
```

## The VideoStreamInfo object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"VideoStreamInfo":{"type":"object","description":"Information about video stream. This information is mostly static but may change based on a user request.","required":["stream_id","type","codec","sensor_width","sensor_height","lens_focal_length","zoom_min","zoom_max","can_do_snapshot"],"properties":{"stream_id":{"description":"Unique video stream identifier.","type":"string"},"type":{"$ref":"#/components/schemas/VideoStreamType"},"frame_width":{"description":"Video frames width. Presented for fixed resolution encoders.","type":"integer"},"frame_height":{"description":"Video frames height. Presented for fixed resolution encoders.","type":"integer"},"sensor_width":{"description":"Sensor width in mm.","type":"number"},"sensor_height":{"description":"Sensor height in mm.","type":"number"},"lens_focal_length":{"description":"Lens focal length in mm. This value is constant and is not affected by zoom. This value corresponds to the `zoom_min` value.\n","type":"number"},"zoom_min":{"description":"Minimum zoom level.","type":"number"},"zoom_max":{"description":"Maximum zoom level.","type":"number"},"codec":{"description":"Video codec. Possible values:\n  * `H.264`\n","type":"string"},"rtsp_url":{"description":"RTSP video stream url.","type":"string"},"rtsps_url":{"description":"RTSPS encoded video stream url.","type":"string"},"can_do_snapshot":{"description":"If true then the video stream supports snapshot functionality. This means that the video stream can provide a snapshot image.\n","type":"boolean"}}},"VideoStreamType":{"type":"string","description":"Video stream type. Possible values:\n  * `Color` - regular color video stream.\n  * `Thermal` - thermal video stream.\n"}}}}
```

## The VideoStreamType object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"VideoStreamType":{"type":"string","description":"Video stream type. Possible values:\n  * `Color` - regular color video stream.\n  * `Thermal` - thermal video stream.\n"}}}}
```

## The VideoStreamState object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"VideoStreamState":{"type":"object","description":"Frequently changing information about video stream","required":["stream_id","is_streaming"],"properties":{"stream_id":{"description":"Unique video stream identifier.","type":"string"},"is_streaming":{"description":"If true then the video stream is currently streaming.\n","type":"boolean"},"timestamp":{"description":"Video timestamp of the last video frame. For RTP video streams this is the RTP timestamp.\n","type":"number"},"fov_horizontal":{"description":"Horizontal field of view in degrees.","type":"number"},"fov_vertical":{"description":"Vertical field of view in degrees.","type":"number"},"pan_ned":{"description":"Camera pan angle in degrees in NED coordinates.\n  * 0 - The camera is looking North.\n  * +90 - The camera is looking East.\n  * +180 - The camera is looking South.\n  * -90 - The camera is looking West.\n","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"tilt_ned":{"description":"Camera tilt angle in degrees in NED coordinates.\n  * 0 - The camera is level, looking straight ahead.\n  * -90 - The camera is looking straight up.\n  * +90 - The camera is looking straight down towards gravity vector.\n","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"roll_ned":{"description":"Camera roll angle in degrees in NED coordinates.\n  * 0 - The camera is level, with the top facing upward.\n  * +90 - The top of the camera is rotated to the right.\n  * +180 - The top of the camera is facing downward (the same direction as gravity vector).\n  * -90 - The top of the camera is rotated to the left.\n","type":"number","minimum":-180,"exclusiveMinimum":true,"maximum":180},"zoom_level":{"description":"Current zoom level.","type":"number"},"thermal_color_palette":{"description":"Thermal color palette. This property is present only for thermal video streams. If the video stream is not thermal then this property is absent.\n","$ref":"#/components/schemas/ThermalColorPalette"}}},"ThermalColorPalette":{"type":"string","description":"Thermal color palette. Possible values:\n  * `WhiteHot`\n  * `BlackHot`\n  * `Rainbow`\n  * `RainbowHighContrast`\n  * `Ironbow`\n  * `Lava`\n  * `Arctic`\n  * `Glowbow`\n  * `GradedFire`\n  * `Hottest`\n"}}}}
```

## The ThermalColorPalette object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"ThermalColorPalette":{"type":"string","description":"Thermal color palette. Possible values:\n  * `WhiteHot`\n  * `BlackHot`\n  * `Rainbow`\n  * `RainbowHighContrast`\n  * `Ironbow`\n  * `Lava`\n  * `Arctic`\n  * `Glowbow`\n  * `GradedFire`\n  * `Hottest`\n"}}}}
```

## The ControlZoomRequest object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"ControlZoomRequest":{"type":"object","description":"Request to set zoom level.","required":["zoom_level"],"properties":{"zoom_level":{"description":"New zoom level to set. Must be in the range from `zoom_min` to `zoom_max`.","type":"number"}}}}}}
```

## The ControlThermalPaletteRequest object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"ControlThermalPaletteRequest":{"type":"object","description":"Request to set thermal color palette.","required":["thermal_color_palette"],"properties":{"thermal_color_palette":{"description":"New thermal color palette to set.","allOf":[{"$ref":"#/components/schemas/ThermalColorPalette"}]}}},"ThermalColorPalette":{"type":"string","description":"Thermal color palette. Possible values:\n  * `WhiteHot`\n  * `BlackHot`\n  * `Rainbow`\n  * `RainbowHighContrast`\n  * `Ironbow`\n  * `Lava`\n  * `Arctic`\n  * `Glowbow`\n  * `GradedFire`\n  * `Hottest`\n"}}}}
```

## The RecordingsState object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"RecordingsState":{"type":"object","description":"Current state of the video recorder.","required":["available_space","total_space","is_recording"],"properties":{"recording_id":{"type":"string","description":"ID of the recording."},"started_recording_timestamp":{"type":"string","format":"date-time","description":"Last time a recording was started since boot, or zero otherwise."},"stopped_recording_timestamp":{"type":"string","format":"date-time","description":"Last time a recording was stopped, or current time if recording."},"is_recording":{"type":"boolean","description":"Whether the recorder is currently running."},"recording_seconds":{"type":"integer","format":"int32","description":"Number of seconds the current recording has been running."},"available_space":{"type":"integer","description":"Bytes available to store video recordings","format":"int64","minimum":0},"occupied_space":{"type":"integer","description":"Bytes currently occupied by video recordings","format":"int64","minimum":0},"total_space":{"type":"integer","description":"Total bytes available for video recordings","format":"int64","minimum":0}}}}}}
```

## The Recording object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"Recording":{"type":"object","description":"Represents a video recording, including video files and metadata.","required":["recording_id","is_being_recorded","videos"],"properties":{"recording_id":{"type":"string","description":"Identifier of the recording."},"is_being_recorded":{"type":"boolean","description":"Whether this recording is currently being recorded."},"videos":{"type":"array","items":{"$ref":"#/components/schemas/VideoFile"}}}},"VideoFile":{"description":"Represents a video file in a recording, including metadata.","type":"object","required":["type","recording_id","file_id","size","is_recording"],"properties":{"type":{"$ref":"#/components/schemas/VideoStreamType"},"recording_id":{"type":"string","description":"ID of the video recording"},"file_id":{"type":"string","description":"Identifier of the video file. Used for downloading."},"size":{"type":"integer","format":"int64"},"is_recording":{"type":"boolean"}}},"VideoStreamType":{"type":"string","description":"Video stream type. Possible values:\n  * `Color` - regular color video stream.\n  * `Thermal` - thermal video stream.\n"}}}}
```

## The VideoFile object

```json
{"openapi":"3.0.4","info":{"title":"Fotokite API","version":"1.1.2"},"components":{"schemas":{"VideoFile":{"description":"Represents a video file in a recording, including metadata.","type":"object","required":["type","recording_id","file_id","size","is_recording"],"properties":{"type":{"$ref":"#/components/schemas/VideoStreamType"},"recording_id":{"type":"string","description":"ID of the video recording"},"file_id":{"type":"string","description":"Identifier of the video file. Used for downloading."},"size":{"type":"integer","format":"int64"},"is_recording":{"type":"boolean"}}},"VideoStreamType":{"type":"string","description":"Video stream type. Possible values:\n  * `Color` - regular color video stream.\n  * `Thermal` - thermal video stream.\n"}}}}
```


