> ## Documentation Index
> Fetch the complete documentation index at: https://firmngin.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Flash enrollment API

> Enroll a client installation and use DPoP-bound access tokens

Base URL: `https://api.firmngin.dev/api/saas/v1/flash`

Enrollment is the second authentication mode. It binds a client installation to an ES256 key so data requests use short-lived DPoP tokens instead of sending the API key on every request.

Use enrollment when the app is distributed to user machines, when a leaked API key should not be enough to act as an existing installation, or when you need per-installation revocation. For a simple internal tool, the API key mode is usually enough.

## Endpoints

| Method | Path | Auth | Description |
| - | - | - | - |
| `POST` | `/enroll/challenge` | API key | Create a single-use enrollment challenge. |
| `POST` | `/enroll` | API key | Register the installation public key and issue tokens. |
| `POST` | `/token` | Refresh + DPoP | Rotate the refresh token and issue a new access token. |
| `GET` | `/me` | DPoP | Read the current installation. |
| `GET` | `/installations` | API key | List installations created by the key. |
| `POST` | `/installations/{id}/revoke` | API key | Revoke one installation and its refresh tokens. |

## Challenge

```http theme={null}
POST /api/saas/v1/flash/enroll/challenge
Authorization: Bearer fng_pat_...
```

```json theme={null}
{
  "data": {
    "challenge": "…",
    "expires_at": "2026-11-04T10:10:00Z"
  }
}
```

## Enroll

```http theme={null}
POST /api/saas/v1/flash/enroll
Authorization: Bearer fng_pat_...
Content-Type: application/json
```

```json theme={null}
{
  "challenge": "…",
  "public_key_jwk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "…",
    "y": "…"
  },
  "signature": "…",
  "app_name": "flash-tool",
  "app_version": "1.0.0",
  "build_hash": "…",
  "os": "your-os",
  "machine_hash": "…"
}
```

```json theme={null}
{
  "data": {
    "installation_id": "…",
    "status": "active",
    "access_token": "…",
    "token_type": "DPoP",
    "expires_in": 900,
    "refresh_token": "…"
  }
}
```

`signature` is the ES256 signature over **SHA-256(challenge)**. The public key must be P-256. One API key can have at most three active installations.

## DPoP request

```http theme={null}
GET /api/saas/v1/flash/firmwares
Authorization: DPoP <access-token>
DPoP: <proof-jwt>
```

Proof claims: `htm`, `htu`, `iat`, `jti`, and `ath`. Proof header: `typ: "dpop+jwt"` and `jwk`.

## Refresh

```http theme={null}
POST /api/saas/v1/flash/token
Content-Type: application/json
DPoP: <proof-jwt>

{ "refresh_token": "…" }
```

The refresh proof omits `ath`. Refresh tokens rotate; reuse revokes the family.

## Installations

```http theme={null}
GET /api/saas/v1/flash/installations
Authorization: Bearer fng_pat_...
```

```http theme={null}
POST /api/saas/v1/flash/installations/{id}/revoke
Authorization: Bearer fng_pat_...
```

Revocation invalidates the installation's access tokens on the next request and revokes its refresh tokens.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.