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

# Option Sets API

> Keep a Select's options current from your own system

An **Option Set** is a named list your onboarding flows can point at. Editing it reaches devices
without republishing any flow, so a list that changes on your side — locations, plans, inventory —
stays current without anyone editing a flow.

Two endpoints matter: one your **system** calls to push the list, and one the **SDK** calls to read
it. You only need the first.

## Push your list

```http theme={null}
POST https://api.appdna.ai/api/v1/sdk/option-sets/{setId}/sync
x-api-key: pk_live_…
x-api-secret: sk_live_…
Content-Type: application/json
```

```json theme={null}
{
  "mode": "replace",
  "items": [
    { "value": "sunrise", "label": "Sunrise Estate", "sort_order": 0 },
    { "value": "southridge", "label": "Southridge", "option_data": { "subtitle": "Lakeside" } }
  ]
}
```

Authenticate with the **existing key pair** from Console → Settings → SDK. The public key
identifies the app and the secret proves it; both live and sandbox pairs work, so you can stage
against sandbox and repoint the same code at production.

### Modes

| Mode                | Behaviour                                                             |
| ------------------- | --------------------------------------------------------------------- |
| `merge` *(default)* | Adds and updates the items you send. Anything you omit is left alone. |
| `replace`           | A full sync. Anything you omit is **archived**.                       |

<Warning>
  `replace` is the right mode for a nightly full export, but it acts on exactly what you send. If a
  bug truncates your payload, a short list archives most of the set. `merge` is the default for that
  reason — its worst case is "some items not updated".
</Warning>

### What it does and does not do

* **Never deletes.** An item you stop sending is archived: hidden from users, kept so answers that
  reference it still resolve. Send it again and it comes back.
* **Never rewrites a locked value.** `value` is the analytics key. Once an answer has recorded it,
  a row that would change it is refused **on its own** — the rest of the file still lands. Labels
  and presentation can still change.
* **Bumps the set version**, so devices pick the change up on next launch.

### Response

```json theme={null}
{
  "data": {
    "set_id": "…", "mode": "replace", "version": 12,
    "created": 3, "updated": 141, "archived": 2, "rejected": []
  }
}
```

Alert on these rather than diffing yourself — `"archived": 400` out of 420 is the shape of a
truncated export, and it is visible here before anyone notices on a device.

### Limits

|                   |                            |
| ----------------- | -------------------------- |
| Items per request | 5,000                      |
| Rate limit        | 20 requests/minute per key |

A set can hold far more than 5,000 items — send them across several `merge` calls, then a final
`replace` if you need omissions archived.

## Read the list (SDK)

```http theme={null}
GET /api/v1/sdk/option-sets/{setId}?cursor=&q=
x-api-key: pk_live_…
```

The SDKs call this themselves; it is documented because it is what makes an unbounded list
possible. A published flow carries only the first page, and the SDK pages and searches from here.
Search is server-side and accent-insensitive, so `malaga` finds `Málaga Estate`.
