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

# Create WiFi Config Grant

> Create a stateless grant for configuring WiFi credentials on a device via BLE

Create a WiFi configuration grant for a device. The grant is a stateless JWT that authorizes the companion app to send encrypted WiFi credentials to the device over BLE.

The device uses the grant to derive a session key (`K_session`) for decrypting the WiFi credentials. No WiFi passwords are stored on the backend — the grant is purely an authorization token.

<Note>
  Only devices with the WiFi Upload capability (`0x02`) support WiFi configuration. Attempting to create a grant for a non-WiFi device returns a `400` error.
</Note>

## Authentication

Requires an [API key](/authentication) with `devices:write` scope.

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://api.bota.dev/v1/devices/dev_abc123/wifi-config/grant \
    -H "Authorization: Bearer sk_live_..." \
    -H "Content-Type: application/json" \
    -d '{
      "expires_in_seconds": 900
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.bota.dev/v1/devices/dev_abc123/wifi-config/grant', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer sk_live_...',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      expires_in_seconds: 900,
    }),
  });

  const grant = await response.json();
  // Send grant.grant_blob to device via BLE
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.bota.dev/v1/devices/dev_abc123/wifi-config/grant',
      headers={
          'Authorization': 'Bearer sk_live_...',
          'Content-Type': 'application/json',
      },
      json={
          'expires_in_seconds': 900,
      },
  )

  grant = response.json()
  # Send grant['grant_blob'] to device via BLE
  ```
</RequestExample>

## Path Parameters

<ParamField path="id" type="string" required>
  The device's unique identifier (e.g., `dev_abc123`).
</ParamField>

## Request Body

<ParamField body="expires_in_seconds" type="integer" default={900}>
  How long the grant is valid, in seconds. Minimum 60 (1 minute), maximum 3600 (1 hour). Default is 900 (15 minutes).
</ParamField>

## Response

Returns the grant blob and its expiration timestamp.

<ResponseExample>
  ```json 200 theme={null}
  {
    "grant_blob": "eyJhbGciOiJIUzI1NiIs...",
    "expires_at": "2025-06-15T12:15:00Z"
  }
  ```

  ```json 400 theme={null}
  {
    "error": {
      "code": "device_not_wifi_capable",
      "message": "Device does not support WiFi configuration"
    }
  }
  ```

  ```json 404 theme={null}
  {
    "error": {
      "code": "not_found",
      "message": "Device not found"
    }
  }
  ```
</ResponseExample>

## Response Fields

| Field        | Type   | Description                                        |
| ------------ | ------ | -------------------------------------------------- |
| `grant_blob` | string | Signed grant token to pass to device via Bluetooth |
| `expires_at` | string | Grant expiration timestamp (ISO 8601)              |

## Usage Flow

1. **App scans for WiFi networks** — the SDK provides `scanNetworks()` (Android) and `getCurrentSSID()` (both platforms) so users can pick a network
2. **App requests grant** from your backend (this endpoint)
3. **App writes `grant_blob`** to the device's Bluetooth WiFi Grant characteristic
4. **App encrypts WiFi credentials** using a session key derived from the grant
5. **App writes encrypted credentials** to the device's Bluetooth WiFi Credential characteristic
6. **Device connects to WiFi** and reports status via the Bluetooth WiFi Status characteristic

The [React Native SDK](/api-reference/client-sdks) provides `scanNetworks()` for step 1 and handles steps 3-6 automatically via `BotaClient.devices.configureWiFi()`.

<Warning>
  The `grant_blob` is a single-use authorization token. Each WiFi configuration attempt requires a fresh grant. Grants cannot be reused after expiration or after a successful configuration.
</Warning>
