# SolidPixels Documentation Full documentation aggregated for use in LLM prompts. --- # Documentation Welcome to the SolidPixels developer documentation. This site is the home for guides, concepts, API references, and integration details across the SolidPixels platform. ## Public API Use the Public API to connect your own tools to SolidPixels. You can manage app releases, inspect and update devices, work with installations, and deliver images to connected displays. [Start with the Public API →](/docs/public-api) ## How this documentation is organized Documentation is grouped by product area in the left navigation. Each section can contain its own introduction, concepts, guides, and reference pages, so new areas can be added without changing the overall navigation model. - **Introductions** explain the purpose and core concepts of an area. - **Guides** walk through complete tasks and recommended workflows. - **References** document exact behavior, inputs, outputs, and constraints. The table of contents on the right follows the current page. On smaller screens, it moves into the collapsible **On this page** control above the article. --- # Public API import ApiEndpoint from "@site/src/components/ApiEndpoint"; The SolidPixels Public API lets you manage your account, release app versions, control devices, and push images from your own software. ## Authentication All public API endpoints use Bearer authentication. Include your API key in the `Authorization` header of every request: ```http title="Authorization header" Authorization: Bearer ``` :::warning[Keep your API key private] Create and revoke named keys in the SolidPixels app under **Development Resources → API keys**. A key is displayed only once when it is created, so copy it immediately and store it securely. You must own at least one device before you can create a key. ::: ## Your account Return the email address and creation time for the authenticated account. ```http title="Request" GET /v1/account/ Authorization: Bearer ``` ```json title="200 response" { "email": "person@example.com", "createdAt": "2025-01-15T12:30:00.000Z" } ``` ## Explore the API - **[Apps](/docs/public-api/apps)** — discover available apps, submit immutable versions for review, and deploy or roll back an approved release. - **[Devices](/docs/public-api/devices)** — list devices, inspect their state, update settings, and manage installations. - **[Push images](/docs/public-api/push-images)** — send a transient image to a device or create a persistent rotation entry. Every list endpoint returns a bare JSON array. Unless an endpoint says otherwise, invalid bodies return `400`, missing resources return `404`, and requests without permission to access a resource return `403`. --- # Apps import ApiEndpoint from "@site/src/components/ApiEndpoint"; Use the apps endpoints to discover content that can be installed on a device and to manage releases for apps owned by your account. ## List available apps Return all apps currently available to install as a flat, uncategorized list. ```http title="Request" GET /v1/apps Authorization: Bearer ``` ```json title="200 response" [ { "id": "app-id", "name": "Weather", "description": "Current conditions and forecast for your location.", "version": "1.3.0", "author": { "name": "SolidPixels" } } ] ``` The response is a JSON array and does not group apps by category. If no apps are available, the endpoint returns `200 []`. ## App version lifecycle An app has an editable draft and a separately deployed version. Saving changes updates the draft only. Uploading a version creates an immutable snapshot with a `PENDING` status and submits it for review; it does not publish the draft. The review can have one of three outcomes: - Approval changes the version to `APPROVED` and publishes it immediately. - A change request changes the version to `CHANGES_REQUESTED` and includes feedback you can address in a new submission. - Rejection changes the version to `REJECTED` without affecting the currently deployed release. Only one version per app can await review at a time. An app's first submission puts the app in `pending` status. Later submissions leave an active app and its current release live throughout review. A new app is not listed or installable until its first version is approved. Installations automatically use the app's currently deployed version. Deploying a previous approved version therefore rolls every installation back without requiring you to update those installations individually. Draft, pending, changes-requested, and rejected versions cannot be deployed. :::note[App identifiers] `appId` can be the app ID returned by SolidPixels or its slug. Your API key can manage apps owned by the same account. ::: ## List versions List a private app's immutable versions, newest first. This endpoint is available only for private apps. ```http title="Request" GET /v1/apps/{appId}/versions Authorization: Bearer ``` ```json title="200 response" [ { "id": "version-id", "version": "1.1.0", "scriptLanguage": "STARLARK", "checksum": "6e409...", "status": "APPROVED", "reviewedAt": "2026-09-08T16:00:00.000Z", "rejectionReason": null, "reviewSummary": null, "reviewComments": [], "createdAt": "2026-09-08T15:30:00.000Z", "deployed": true }, { "id": "previous-version-id", "version": "1.0.0", "scriptLanguage": "STARLARK", "checksum": "826a1...", "status": "REJECTED", "reviewedAt": "2026-09-01T14:00:00.000Z", "rejectionReason": "The app fails when the location is omitted.", "reviewSummary": null, "reviewComments": [], "createdAt": "2026-09-01T12:00:00.000Z", "deployed": false } ] ``` A public app—or a legacy app without the `private` attribute—returns `403`. A private app without uploaded versions returns `200 []`. ## Upload an app version Create an immutable app snapshot and submit it for review. ```http title="Request" POST /v1/apps/{appId}/upload Authorization: Bearer Content-Type: application/json ``` ```json title="Request body" { "version": "1.1.0", "scriptContent": "def main():\n return render.Text(\"Hello\")", "scriptLanguage": "STARLARK" } ``` `version` must be 1–64 characters and may contain letters, numbers, dots, dashes, and underscores. `scriptLanguage` must be `STARLARK` or `TYPESCRIPT`. Unknown fields are rejected. Uploading does not change the currently deployed version. ```json title="201 response" { "id": "version-id", "version": "1.1.0", "scriptLanguage": "STARLARK", "checksum": "6e409...", "status": "PENDING", "reviewedAt": null, "rejectionReason": null, "reviewSummary": null, "reviewComments": [], "createdAt": "2026-09-08T15:30:00.000Z", "deployed": false } ``` Uploading a version name that already exists, or submitting while another version of the app is awaiting review, returns `409`. Invalid bodies return `400`. ## Deploy or roll back an app Deploy an approved version. Selecting an older version rolls the app back. ```http title="Request" POST /v1/apps/{appId}/deploy Authorization: Bearer Content-Type: application/json ``` ```json title="Request body" { "version": "1.1.0" } ``` Every installation uses the selected version on its next render. ```json title="200 response" { "id": "version-id", "version": "1.1.0", "scriptLanguage": "STARLARK", "checksum": "6e409...", "status": "APPROVED", "reviewedAt": "2026-09-08T16:00:00.000Z", "rejectionReason": null, "reviewSummary": null, "reviewComments": [], "createdAt": "2026-09-08T15:30:00.000Z", "deployed": true } ``` Missing apps or versions return `404`; attempting to deploy a version that has not been approved returns `409`; requests without permission to manage the app return `403`. --- # Devices import ApiEndpoint from "@site/src/components/ApiEndpoint"; Use the device endpoints to inspect devices connected to your account, update their settings, and manage their installed apps. :::note[Device identifiers] `deviceId` can be the device ID returned by the API, its serial number, or its MAC address. Your API key can access devices owned by the same account. ::: ## List devices List the devices connected to the authenticated account, oldest first. ```http title="Request" GET /v1/devices Authorization: Bearer ``` ```json title="200 response" [ { "id": "device-id", "name": "Kitchen", "brightness": 30, "volume": 50, "lastOnline": "2026-09-08T15:30:00.000Z", "autoDim": true, "timezone": "America/Lima", "scheduleInterval": 30, "sleep": { "enabled": true, "start": "22:00", "end": "07:00" } } ] ``` Accounts without devices receive `200 []`. ## Get a device Return one device using the same response shape as the list endpoint. ```http title="Request" GET /v1/devices/{deviceId} Authorization: Bearer ``` Missing devices return `404`; requests without permission to access the device return `403`. ## Update a device Update only the settings included in the request body. ```http title="Request" PATCH /v1/devices/{deviceId} Authorization: Bearer Content-Type: application/json ``` At least one supported field is required. Omitted fields remain unchanged and unknown fields are rejected. ```json title="Request body" { "brightness": 75, "sleepEnabled": true, "sleepStart": "23:00" } ``` | Field | Type | Validation | | --- | --- | --- | | `name` | string | 1–25 characters | | `brightness` | integer | 0–100 | | `volume` | integer | 0–100 | | `autoDim` | boolean | — | | `timezone` | string | Available timezone ID | | `sleepEnabled` | boolean | — | | `sleepStart` | string | 24-hour `HH:mm` | | `sleepEnd` | string | 24-hour `HH:mm` | | `scheduleInterval` | integer | At least 15 seconds | The response is the updated device in the same shape returned by `GET /v1/devices`. A partial sleep update preserves any sleep settings you omit. Invalid bodies return `400`, missing devices return `404`, and requests without permission to update the device return `403`. ## List installations List installations in the order they appear in the device's rotation. ```http title="Request" GET /v1/devices/{deviceId}/installations Authorization: Bearer ``` ```json title="200 response" [ { "id": "installation-id", "app": { "id": "app-id", "name": "Weather" }, "createdAt": "2026-09-04T10:00:00.000Z" }, { "id": "pushed-installation-id", "app": null, "createdAt": "2026-09-04T11:00:00.000Z" } ] ``` For an app installation, `id` is the installation ID returned by the API and `app` contains the app ID and name. For an installation created through a push, `id` is the caller-provided `installationId` and `app` is `null`. Missing devices return `404`; requests without permission to access the device return `403`. ## Delete an installation Remove an app or pushed installation from a device. ```http title="Request" DELETE /v1/devices/{deviceId}/installations/{installationId} Authorization: Bearer ``` `installationId` may be the ID returned for an app installation or the caller-provided ID returned for a pushed installation. The installation is matched within the specified device. A successful deletion returns `200 {}`. Missing devices or installations return `404`; requests without permission to update the device return `403`. --- # Push images import ApiEndpoint from "@site/src/components/ApiEndpoint"; Use the push endpoint to display a 64×32 image immediately or add it to a device's regular content rotation. PNG, WebP, and GIF inputs are supported. Display a temporary image or create a persistent rotation entry. ```http title="Request" POST /v1/devices/{deviceId}/push Authorization: Bearer Content-Type: application/json ``` ## Request body | Field | Type | Required | Behavior | | --- | --- | --- | --- | | `image` | string | Yes | Base64 or a PNG/WebP/GIF data URL. The image must be 64×32 and at most 192 KiB. PNG and GIF input is converted to lossless WebP. | | `duration` | number | No | Temporary display duration in seconds. Defaults to `5`; allowed values are `5`, `10`, `15`, `30`, `35`, `40`, and `45`. Ignored when `installationId` is present. | | `installationId` | string | No | Creates or updates a persistent entry in the device's rotation. | | `background` | boolean | No | When `true`, updates a persistent installation without displaying it immediately. Use with `installationId`. | A successful request returns `200 {}`. Invalid requests return `400`, missing devices return `404`, and requests without permission to update the device return `403`. ## Display a temporary image Omit `installationId` to display the image immediately for a limited time. The device resumes its regular rotation when the duration ends. A newer push replaces any temporary image currently on the display. ```json title="Request body" { "image": "data:image/webp;base64,", "duration": 10 } ``` If you omit `duration`, the image is shown for 5 seconds. ## Create a persistent installation Include `installationId` to add the image to the device's content rotation. Choose a stable identifier from your application so you can update or delete the same installation later. ```json title="Request body" { "image": "data:image/png;base64,", "installationId": "daily-metrics" } ``` The image is displayed immediately, then appears in the regular rotation. Its initial display duration uses the device's configured `scheduleInterval`. Sending another request with the same `installationId` replaces the existing image. To update the rotation without interrupting the current display, set `background` to `true`: ```json title="Background update" { "image": "data:image/png;base64,", "installationId": "daily-metrics", "background": true } ``` Use the [delete installation endpoint](/docs/public-api/devices#delete-an-installation) when you no longer want the image in the device's rotation.