# List contact attribute keys

`GET /v1/attributes`

Requires an API key with the `attributes:read` scope. [About keys and scopes](/docs/api/authentication)

Every attribute key your contacts carry, with its inferred type and how many contacts have it: the pickers for segment rules and merge tags. Read from an index up to five minutes old (a contact import refreshes it at once). A `list` key takes `contains`, `notContains`, `exists` and `notExists` in rules. `masked` keys are listed, but their values are hidden from members and embed sessions.

## Query parameters

- `limit` (integer, optional, min > 0, max 100, default `20`)
- `cursor` (string, optional, 1–2048 characters)

## Returns

Returns `200 OK` with a list of `Attribute` objects in `data`, and the next page's cursor in `meta` (see [pagination](/docs/api/pagination)). Otherwise returns an error; [Errors](/docs/api/errors) lists every code and which to retry.

- `key` (string, required) — The attribute key, as written on contacts.
- `type` (string, required, one of `string`, `number`, `boolean`, `date`, `list`, `mixed`) — Inferred from the values held. `list`: every value is an array (`["running", "yoga"]`, a form's checkboxes); `mixed`: more than one type.
- `contactCount` (integer, required, min 0, max 9007199254740991) — Contacts that have this key.
- `masked` (boolean, required) — Masked in workspace settings: members see the key, not its values.

## Example

```bash
curl https://api.kirora.io/v1/attributes \
  -H "Authorization: Bearer $KIRORA_API_KEY"
```

Response `200`:

```json
{
  "data": [
    {
      "key": "key_example",
      "type": "string",
      "contactCount": 0,
      "masked": true
    }
  ],
  "meta": {
    "pagination": {
      "limit": 1,
      "nextCursor": "nextCursor_example"
    }
  }
}
```
