---
title: "Dashboard client"
description: "A Dashboard client calls the Formlabs Web API, the API behind Dashboard, with a developer token from the SDK."
url: https://developer.formlabs.com/core-concepts/dashboard-client/
---

# Dashboard client

A *Dashboard client* calls the Formlabs Web API, the API behind Dashboard, at
`https://api.formlabs.com/developer/v1/`. It reads the same printers, print history,
Printer Groups, and group queues that Dashboard shows, so a script can build a usage
report across every printer on the account.

The SDK has no methods for the Formlabs Web API endpoints, so the client has two
parts. A `FormlabsClient` with developer credentials supplies the token, and an HTTP
client sends the requests. To send a print job to a group queue, as **Upload to Queue**
does, use the PreForm client. For more information, see [PreForm client](https://developer.formlabs.com/core-concepts/preform-client.md).

## What each part does

The two parts split the work:

- **`FormlabsClient`:** Holds the client ID and client secret, requests the developer
  token, caches it, and requests a new one 300 seconds before it expires. Closing the
  client revokes the token.
- **HTTP client:** Sends each request with the token in the `Authorization` header.
  The examples on this page use `httpx`, which the SDK installs.

To create the client ID and client secret in Dashboard, see
[Install the Developer Kit](https://developer.formlabs.com/getting-started/install.md#connect-to-dashboard).

## Attach the token to each request

An `httpx.Auth` class asks the session for the token on every request, so a refreshed
token reaches the next request:

```python
class DeveloperTokenAuth(httpx.Auth):
    """Adds the developer token to each request, and retries once after a 401."""

    def __init__(self, session):
        self.session = session

    def auth_flow(self, request):
        # The session returns its cached token until 300 seconds before it expires.
        request.headers["Authorization"] = f"Bearer {self.session.developer_token()}"
        response = yield request
        if response.status_code == 401:
            # The server revoked the token. Drop it so the session mints a new one.
            self.session.invalidate(TokenKind.DEVELOPER)
            token = self.session.developer_token()
            request.headers["Authorization"] = f"Bearer {token}"
            yield request
```

A `401` response means the server rejected a token the session considers valid, for
example after the token was revoked. The `invalidate` method drops the cached token,
and the retry carries a new one.

## Create the client

The HTTP client takes the Formlabs Web API base URL and the auth class:

```python
credentials = FormlabsCredentials(
    client_id=os.environ["FORMLABS_CLIENT_ID"],
    client_secret=os.environ["FORMLABS_CLIENT_SECRET"],
)

with FormlabsClient(credentials=credentials) as client:
    # Closing the client revokes the developer token, so every request runs inside
    # this with block.
    with httpx.Client(
        base_url="https://api.formlabs.com/developer/v1/",
        auth=DeveloperTokenAuth(client.auth),
    ) as dashboard:
```

Creating `FormlabsClient` makes no network request. A rejected client ID or secret
raises `InvalidCredentialsError` on the first request, when the session requests the
token.

## Send a request

Paths are relative to the base URL:

```python
response = dashboard.get("printers/")
response.raise_for_status()
for printer in response.json():
    print(printer["serial"])
```

The `printers/` endpoint returns every printer on the account. Some list endpoints
wrap their items in an envelope with `count` and `results`. For more information, see the
[Formlabs Web API reference](https://formlabs-dashboard-api-resources.s3.amazonaws.com/formlabs-web-api-latest.html).

## What the Formlabs Web API covers

The Formlabs Web API reads and manages what Dashboard shows:

| Area | Paths |
| --- | --- |
| Printers | `printers/`, `printers/{printer_serial}/` |
| Print history | `prints/`, `printers/{printer_serial}/prints/` |
| Printer Groups and group queues | `groups/`, `groups/{group_id}/members/`, `groups/{group_id}/queue/` |
| Consumables | `cartridges/`, `tanks/` |
| Events | `events/` |

For every endpoint, see the
[Formlabs Web API reference](https://formlabs-dashboard-api-resources.s3.amazonaws.com/formlabs-web-api-latest.html).

## What's next

- [Scene](https://developer.formlabs.com/core-concepts/scene.md)
