---
title: About HTTP API
slug: bar/dev/http-api
description: Learn about BUSY Bar’s HTTP API, its capabilities, how to authorize your requests, and access the API reference and libraries
image: https://archbee-image-uploads.s3.amazonaws.com/3StCFqarJkJQZV-7N79yY/K1X_qOmHp6PEqgG1Z86US_busy-docs-prev.jpg
docTags: 
createdAt: 2026-07-08T13:37:54.940Z
---

::Image[]{src="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/IkfzK-kzJ0SiFV4TF5D3L_busy-bar-http-api.png" size="90" isUploading="false" width="1500" height="1074" darkWidth="1500" darkHeight="1074" showCaption="false"}

The open HTTP API lets you fully control your BUSY Bar using your own scripts, applications, or services in any programming language. The HTTP API is available over USB, Wi-Fi, and the internet.

On this page, you’ll learn about the HTTP API:

- [Capabilities%section%](docId\:H4whpEXTNlYjSR9PlxsAr)
- [Authentication%section%](docId\:H4whpEXTNlYjSR9PlxsAr)
- [HTTP API reference%section%](docId\:H4whpEXTNlYjSR9PlxsAr)
- [Try the API from the HTTP API reference%section%](docId\:H4whpEXTNlYjSR9PlxsAr)
- [Display an image and text using a Python script%section%](docId\:H4whpEXTNlYjSR9PlxsAr)
- [busylib libraries%section%](docId\:H4whpEXTNlYjSR9PlxsAr)

***

# Capabilities

- **Timer control** — control the BUSY and CUSTOM modes
- **Display control** — render text and images on both displays, adjust brightness
- **Audio control** — upload and play audio files, adjust volume
- **Real-time updates** — get display frames and BUSY Bar state changes over WebSocket
- **Input simulation** — emulate button presses and scroll wheel events
- **File management** — upload, organize, and delete files stored on the BUSY Bar
- **Firmware updates** — update firmware from a local file or over the internet
- **Wi-Fi and Bluetooth** — scan and connect the BUSY Bar to Wi-Fi networks, enable BLE advertising, remove BLE pairings, and check connection status
- **BUSY account** — link or unlink the BUSY Bar with your account, get account info
- **Matter integration** — connect the BUSY Bar to your smart home
- **System config** — set the BUSY Bar name, system time, time zone, and more
- **System info** — get BUSY Bar status, power, and firmware details

***

# How it works

The HTTP API follows a client-server architecture. The BUSY Bar acts as an **HTTP Server**, listening for incoming requests from an **HTTP Client**. When the BUSY Bar receives a request, it processes it and generates a response.

![](https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/iX1a0ZGC8GBg0kjCEvZJu_http-communication.jpg)

The HTTP client can be any application capable of sending HTTP requests, such as a smart home system, a script, a desktop or mobile application, or even a web browser. For the simplest test, connect BUSY Bar to your computer via USB and enter: `10.0.4.20/api/status/firmware`. The browser will send an HTTP request to your BUSY Bar and display its response:

![](https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/MpHOiaXv4lohpsJFm72HJ_request-and-response-newest.jpg)

An HTTP request URL consists of:

- **Base URL**, which depends on how BUSY Bar is connected.
- **Endpoint**, which identifies the type of request to BUSY Bar. All available endpoints are listed in the HTTP API reference.

::Image[]{src="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/wDDklXlHPWIs8rxtA6kzI_base-url-and-endpoint-new.jpg" size="90" isUploading="false" position="center" width="1800" height="666" darkWidth="1800" darkHeight="666" showCaption="false"}

## Base URL

The base URL for HTTP API requests depends on how your BUSY Bar is connected:

| **Connection method** | **Base URL**                   | **Authentication** |
| --------------------- | ------------------------------ | ------------------ |
| USB                   | `http://10.0.4.20/api`         | Not required       |
| Wi-Fi (LAN)           | `http://XX.XX.XX.XX/api`       | Required           |
| Internet              | `https://api.busy.app/busybar` | Required           |

:::hint{type="info"}
:inlineImage[]{src="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/JzzAMWPfMWluW80KVupgz-20260311-152018.png" alt caption width="76" height="88"}**&#x20;&#x20;**<font color="#2B7EFF">**For Wi-Fi connections**</font>

To find your BUSY Bar's IP address, go to <font color="#475F85">**Settings → Wi-Fi → \[Your Wi-Fi AP name\] → View IP Address**</font>.
:::

**Authentication:** Wi-Fi (LAN) and internet connections require authentication. For details, see [Authentication%section%](docId\:H4whpEXTNlYjSR9PlxsAr)



## Wi-Fi access

:::hint{type="info"}
:inlineImage[]{src="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/JzzAMWPfMWluW80KVupgz-20260311-152018.png" alt caption width="76" height="88"}**&#x20;&#x20;**<font color="#2B7EFF">**Enable Wi-Fi access to control BUSY Bar over Wi-Fi**</font>

Wi-Fi (LAN) connections to BUSY Bar are <font color="#475F85">**disabled by default for security reasons**</font>.
:::

To enable Wi-Fi access to BUSY Bar:

::::WorkflowBlock
:::WorkflowBlockItem
Connect your BUSY Bar to a computer via USB.
:::

:::WorkflowBlockItem
Open the BUSY Bar local web interface in a web browser: [http://10.0.4.20](http://10.0.4.20)
:::

:::WorkflowBlockItem
On the **Network** tab, in the **HTTP API** section, turn on **HTTP API access**.
:::

:::WorkflowBlockItem
Click **Set password and enable**, and set a password.
:::
::::

From now on, your BUSY Bar will ask for this password every time you log in to the web interface via Wi-Fi. You’ll also need to include this password in all HTTP requests for authentication.

***

# Authentication

Authentication is how the device verifies that an incoming HTTP API request was actually sent by its owner or someone the owner trusts. Without authentication, BUSY Bar returns a `403 Forbidden` error in response to the request.

The authentication method depends on how you connect to BUSY Bar: via USB, Wi-Fi, or the internet.



## :inlineImage[]{src="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/E6JCd96P1l0K38ah5ZGX3_usb-header.png" alt caption width="96" height="96"} Via USB

A USB connection is considered a secure communication channel, so authentication is not used over USB. You can send any HTTP API requests to the device at its IP address `10.0.4.20` without authentication.



## :inlineImage[]{src="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/HKFo9DlWwktKDMQxhDYyZ_wifi-header.png" alt caption width="96" height="96"} Via Wi-Fi (LAN)

HTTP API requests over Wi-Fi are authenticated using a password that is set in the local web interface. Wi-Fi access must be enabled first. [Learn how to enable Wi-Fi access. ](docId\:H4whpEXTNlYjSR9PlxsAr)

Include this password in the `X-API-Token` header for every HTTP request sent to the BUSY Bar over Wi-Fi.

Here are a few examples:

::::Tabs
:::Tab{title="curl"}
```bash
curl -X GET \
  "http://[BUSY Bar IP address]/api/status" \
  -H "Accept: application/json" \
  -H "X-API-Token: <your password>"
```
:::

:::Tab{title="JavaScript"}
```javascript
const response = await fetch("http://[BUSY Bar IP address]/api/status", {
  headers: {
    "Accept": "application/json",
    "X-API-Token": "<your password>",
  },
});
```


:::

:::Tab{title="Python"}
```python
import requests

response = requests.get(
    "http://[BUSY Bar IP address]/api/status",
    headers={
        "Accept": "application/json",
        "X-API-Token": "<your password>",
    },
)
```
:::
::::

## :inlineImage[]{src="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/6MbcBA4hBEeYXmpjk86-h_web-dark.png" alt caption width="72" height="96"} Via internet

When connecting over the internet, requests are authenticated through an API token. You can generate and manage tokens in your BUSY account. [Learn how to manage API tokens.](docId:3AUwYBGy9fGU_b8DnFm4h)

Include your API token in the `Authorization` header using the `Bearer` authentication scheme for every HTTP request sent to the BUSY Bar over the internet.

Here are a few examples:

::::Tabs
:::Tab{title="curl"}
```bash
curl -X GET \
  "https://api.busy.app/busybar/status" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <your_api_token>"
```
:::

:::Tab{title="JavaScript"}
```javascript
const response = await fetch("https://api.busy.app/busybar/status", {
  headers: {
    "Accept": "application/json",
    "Authorization": "Bearer <your_api_token>",
  },
});
```


:::

:::Tab{title="Python"}
```python
import requests

response = requests.get(
    "https://api.busy.app/busybar/status",
    headers={
        "Accept": "application/json",
        "Authorization": "Bearer <your_api_token>",
    },
)
```
:::
::::

***

# HTTP API reference

![](https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/8Kw3UaT55IMLQsTiEXR-e_api-reference-2-new.jpg)

[HTTP API reference](https://api.busy.app/busybar/docs) is an interactive page where you can:

- **Browse all HTTP API endpoints** — view all supported API requests.
- **View the API schemas** that describe the JSON objects used by the HTTP API.
- **Download the `openapi.yml` file**, which contains the HTTP API specification in the OpenAPI format.
- **Test any API request**. Expand the desired endpoint, click **Try it out**, edit the request parameters or body if necessary, and then click **Execute**.

***

## How to open the HTTP API reference

You can open the HTTP API reference in one of two ways:

### <font color="#ED0018">**Option 1\:**</font> From the BUSY Bar local web interface

Open the following URL in your web browser:

- `http://10.0.4.20/docs` (when connected over USB)
- `http://<BUSY Bar IP address>/docs` (when connected over Wi-Fi)

Alternatively, open the **Network** tab in the local web interface and, in the **HTTP API** section, click either **Over USB** or **Over Wi-Fi**.

This opens the HTTP API reference hosted directly on the BUSY Bar. It documents the version of the HTTP API implemented in the device’s firmware. When you test API requests from the reference page, they are sent directly to the BUSY Bar over Wi-Fi or USB.



### <font color="#ED0018">**Option 2\:**</font> Public HTTP API reference

Open the following URL in your web browser: [https://api.busy.app/busybar/docs](https://api.busy.app/busybar/docs)

In the page header, select your BUSY Bar firmware version to view the corresponding HTTP API reference.

When you test API requests from the public reference page, the requests are sent to your BUSY Bar over the internet through our cloud service.

***

# Try the API from the HTTP API reference

You can send requests to your BUSY Bar right from the HTTP API reference. In the example below, you’ll show text on the front screen and an image on the back screen.

### <font color="#ED0018">**Step 1.**</font> Authenticate (if needed)

To try API requests, you may need to authenticate first, depending on how you access the HTTP API reference:

- **Over USB** (`http://10.0.4.20/docs`) — no authentication needed, just send requests
- **Over Wi-Fi&#x20;**(`http://<BUSY_Bar_IP_address>/docs`) — click **Authorize** and enter the password you set when [enabling Wi-Fi access](docId\:H4whpEXTNlYjSR9PlxsAr)
- **Over the internet** (`api.busy.app/busybar/docs`) — click **Authorize** and enter an [API token](docId:3AUwYBGy9fGU_b8DnFm4h) generated in your BUSY account. When creating the token, select **BUSY Bar** under **Access scope**

::Image[]{src="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/Y--ixUj8wES9DqYP3lQzL_authorize-new1.jpg" size="90" isUploading="false" position="center" width="1800" height="762" darkWidth="1800" darkHeight="762" showCaption="false"}

### <font color="#ED0018">**Step 2.**</font> Upload an image for the back screen

:::hint{type="info"}
:inlineImage[]{src="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/JzzAMWPfMWluW80KVupgz-20260311-152018.png" alt caption width="76" height="88"}**&#x20;&#x20;**<font color="#2B7EFF">**for the back screen**</font>

The file must be no larger than 255 KB. You can download our example image:

::File{src="https://api.archbee.com/api/presign/3StCFqarJkJQZV-7N79yY/niSDzNEL3PyIdPTSodqzx_our-example-image.zip" label="our-example-image.zip"}
:::



Try the endpoint that uploads an image:

:::::WorkflowBlock
:::WorkflowBlockItem
In the **Assets** group, expand <font color="#22C55E">**POST**</font> `api/assets/upload` and click **Try it out**.

![](https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/3P_88kUQro4KKkWnZ8fqc_testing-responses-6-new.jpg)
:::

:::WorkflowBlockItem
In the **Request body**, click **Choose file** and select your file.

![](https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/YO9morBhobOhsQ40kBV6z_testing-responses-7.jpg)
:::

::::WorkflowBlockItem
Click **Execute** to upload the file to your BUSY Bar.

:::hint{type="info"}
The image is now in your BUSY Bar’s memory. To show it, continue to Step 3.
:::
::::
:::::

### <font color="#ED0018">**Step 3.**</font> Display text and an image on the BUSY Bar screens

::::WorkflowBlock
:::WorkflowBlockItem
Scroll down to the <font color="#22C55E">**POST**</font> `/busybar/display/draw` endpoint.
:::

:::WorkflowBlockItem
Expand the endpoint and click **Try it out**.

![](https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/r-FBWKqCMyRaPngoEV0gW_testing-responses-4.jpg)
:::

:::WorkflowBlockItem
*(Optional)* Edit the request body.

For example, change the `text` parameter to show a different text.

![](https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/87Pa-Uii04bCJ-yh6h43s_testing-responses-5.jpg)
:::

:::WorkflowBlockItem
Click **Execute**. Your BUSY Bar will show the text on the front screen and the uploaded image on the back screen.

![](https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/Hi82VmIXuPWW422k3Sqw7_test-responses-draw.jpg)
:::
::::

***

# Display an image and text using a Python script

Now let’s try controlling BUSY Bar with your own code. The Python script below uses the HTTP API to upload a small image and display it on the front screen together with a text message.

![](https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/Fy2jrjgGdXph86SLeK_5W_python-script-example.jpg)



### <font color="#ED0018">**Step 1.**</font> Create the script file

Copy and paste the contents of this block into a file named `test.py` and save it:

:::ExpandableHeading
*Click here to expand the block with the script code&#x20;*:inlineImage[]{src="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/BnDmvlxd6fDnLVlZlpBnN-20260615-181604.png" alt caption width="96" height="96"}

```python
#!/usr/bin/env python3

import argparse
import requests

APP_NAME = "hello_demo"
IMAGE_FILE = "smile.png"


def make_headers(auth_type: str, token: str | None) → dict:
    """Build HTTP headers for the selected authentication method."""

    headers = {
        "Accept": "application/json",
    }

    if auth_type == "usb":
        # USB connection does not require authentication.
        pass

    elif auth_type == "wifi":
        if not token:
            raise ValueError("--token is required when using --auth wifi")
        headers["X-API-Token"] = token

    elif auth_type == "cloud":
        if not token:
            raise ValueError("--token is required when using --auth cloud")
        headers["Authorization"] = f"Bearer {token}"

    else:
        raise ValueError(f"Unknown authentication type: {auth_type}")

    return headers


def upload_image(base_url: str, auth_type: str, token: str | None):
    url = (
        f"{base_url}/assets/upload"
        f"?application_name={APP_NAME}"
        f"&file={IMAGE_FILE}"
    )

    with open(IMAGE_FILE, "rb") as f:
        response = requests.post(
            url,
            headers={
                **make_headers(auth_type, token),
                "Content-Type": "application/octet-stream",
            },
            data=f,
        )

    response.raise_for_status()
    print("Image uploaded.")


def draw(base_url: str, auth_type: str, token: str | None):
    url = f"{base_url}/display/draw"

    payload = {
        "application_name": APP_NAME,
        "elements": [
            {
                "id": "logo",
                "type": "image",
                "display": "front",
                "path": IMAGE_FILE,
                "x": 0,
                "y": 0,
            },
            {
                "id": "text",
                "type": "text",
                "display": "front",
                "text": "Hello world!",
                "font": "extra_large",
                "color": "#00FF00FF",
                "width": 54,
                "align": "top_left",
                "scroll_rate": 800,
                "scroll_start_delay": 1000,
                "scroll_repeat_delay": 2500,
                "x": 18,
                "y": 1,
            },
        ],
    }

    response = requests.post(
        url,
        headers={
            **make_headers(auth_type, token),
            "Content-Type": "application/json",
        },
        json=payload,
    )

    response.raise_for_status()
    print("Display updated.")


def main():
    parser = argparse.ArgumentParser(
        description="Display an image and text on BUSY Bar."
    )

    parser.add_argument(
        "base_url",
        help=(
            "Base URL, including the API path prefix "
            "(e.g. http://10.0.4.20/api or https://api.busy.app/busybar)"
        ),
    )

    parser.add_argument(
        "--auth",
        choices=["usb", "wifi", "cloud"],
        default="usb",
        help="Authentication method (default: usb)",
    )

    parser.add_argument(
        "--token",
        help="Wi-Fi password or Cloud API token",
    )

    args = parser.parse_args()

    base_url = args.base_url.rstrip("/")

    upload_image(base_url, args.auth, args.token)
    draw(base_url, args.auth, args.token)

    print("Done.")


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


:::

### <font color="#ED0018">**Step 2.**</font> Download the image file

Save a 16x16 px PNG image named `smile.png` in the same folder as `test.py`. You can download our example image (:inlineImage[]{src="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/7JT4wNuWOlcuwa2Bk0a0m_smile.png" alt caption width="16" height="16"}):

::File{src="https://api.archbee.com/api/presign/3StCFqarJkJQZV-7N79yY/wtSegFszF6ygddLHns_EO_example-image.zip" label="example-image.zip"}



### <font color="#ED0018">**Step 3.**</font> Set up the Python environment

:::hint{type="info"}
The script requires <font color="#475F85">**Python 3.10 or newer**</font>. If Python is not installed, download it from [python.org](https://www.python.org/downloads/).
:::

Open a terminal in the folder with the script and run:

```bash
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install requests
```

This creates an isolated Python virtual environment and installs the `requests` library that the script depends on.



### <font color="#ED0018">**Step 4.**</font> Run the script

Run the command for your connection type. For Wi-Fi, use the password you set when  [enabling Wi-Fi access](docId\:H4whpEXTNlYjSR9PlxsAr). For an internet connection, use an [API token](docId:3AUwYBGy9fGU_b8DnFm4h) from your BUSY account.

:inlineImage[]{src="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/E6JCd96P1l0K38ah5ZGX3_usb-header.png" alt caption width="96" height="96"}**&#x20;USB**

```bash
python3 test.py http://10.0.4.20/api
```



:inlineImage[]{src="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/HKFo9DlWwktKDMQxhDYyZ_wifi-header.png" alt caption width="96" height="96"}**&#x20;Wi-Fi (LAN)**

For Wi-Fi, use the password you set when [enabling Wi-Fi access](docId\:H4whpEXTNlYjSR9PlxsAr).

```bash
python3 test.py http://<BUSY_Bar_IP_address>/api --auth wifi --token "<your password>"
```



:inlineImage[]{src="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/6MbcBA4hBEeYXmpjk86-h_web-dark.png" alt caption width="72" height="96"}**&#x20;Internet**

For an internet connection, use an [API token](docId:3AUwYBGy9fGU_b8DnFm4h) from your BUSY account. When creating the token, select **BUSY Bar** under **Access scope**.

```bash
python3 test.py https://api.busy.app/busybar --auth cloud --token <your_api_token>
```

If everything works, the terminal will print `Image uploaded.`, `Display updated.`, and `Done.`, and your BUSY Bar will show the image and the "Hello world!" text on the front screen.

***

# busylib libraries

**busylib** is the official open-source library for building applications that interact with BUSY Bar. It provides ready-to-use Python and TypeScript APIs that abstract the underlying HTTP API.



## Advantages

- **Simplifies development** by handling HTTP request construction and response processing. Developers can work with a simple, high-level API without worrying about the underlying HTTP protocol.
- **Implements WebSocket communication** for receiving real-time events from the BUSY Bar and for screen streaming.
- **Supports both synchronous and asynchronous interaction** with BUSY Bar, making it suitable for both simple applications and concurrent workflows.



## Get busylib

We maintain busylib for Python and TypeScript:

::::LinkArray{contentSource="CUSTOM"}
:::LinkArrayItem{headerType="IMAGE" headerImage="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/2nMyL30R83hSoqpG17NSK_ts-logo.jpg"}
**[TypeScript library](https://go.busy.app/typescript-library)**
:::

:::LinkArrayItem{headerType="IMAGE" headerImage="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/ayHOmRd7ESYDHNI9TSIkL_python-logo.jpg"}
**[Python library](https://pypi.org/project/busylib/)**
:::
::::

:::hint{type="info"}
:inlineImage[]{src="https://api.archbee.com/api/optimize/3StCFqarJkJQZV-7N79yY/JzzAMWPfMWluW80KVupgz-20260311-152018.png" alt caption width="76" height="88"} <font color="#2B7EFF">**L**</font>****<font color="#2B7EFF">**ibraries from the community**</font>

There are also libraries for the BUSY Bar HTTP API, built and maintained by the community:

- [BusyBar .NET](https://busybar-dotnet.homotechsual.dev/)
- [busybar.zig](https://tty.fail/mrus/busybar.zig)
:::

