# Profile Attributes


Read-only catalogs for the `ProfileAttributes` dataset on
[Create Audience](/api/v2/audiences#post-apiv2analysesaudiencescreate): the
attribute cascade plus the delivered window its date range is bounded to.

The attribute catalogs form a **three-level cascade** - pick a category, use it
to read the keys available under it, and both to read that key's selectable
values:

```
categories -> keys (?category_ids[]) -> values (?category_ids[], ?key)
```

Each level returns `{ value, text }` rows (plus the parent it cascades from)
where `value` is what the matching field of a `profile_attributes` row accepts
and `text` is the label to show a user. All three levels are paginated.

Every read here is authenticated and JSON-only (bearer token + `Accept:
application/json`) and uses the read rate bucket (120 requests/min per caller).

## Get Profile Attributes Categories {#get-apiv2analysesreferenceprofile-attributescategories}

`GET /api/v2/analyses/reference/profile-attributes/categories`

The first cascade level. `value` is the category id a `profile_attributes`
row's `category_id` takes. Paginated.

### Query parameters

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `page` | integer | No | Page number (standard pagination). |
| `per_page` | integer | No | Items per page, capped at 500. |
| `search` | string | No | Optional free-text filter on the category name (case-insensitive contains). |

{{< tabs >}}

  {{< tab name="cURL" >}}
  ```bash
  curl "https://console.intuizi.com/api/v2/analyses/reference/profile-attributes/categories" \
    -H "Authorization: Bearer <YOUR_TOKEN>" \
    -H "Accept: application/json"
  ```
  {{< /tab >}}

  {{< tab name="Python" >}}
  ```python
  import requests

  res = requests.get(
      "https://console.intuizi.com/api/v2/analyses/reference/profile-attributes/categories",
      headers={"Authorization": "Bearer <YOUR_TOKEN>", "Accept": "application/json"},
  )
  categories = res.json()["data"]["items"]
  ```
  {{< /tab >}}

  {{< tab name="JavaScript" >}}
  ```javascript
  const res = await fetch(
    "https://console.intuizi.com/api/v2/analyses/reference/profile-attributes/categories",
    { headers: { Authorization: "Bearer <YOUR_TOKEN>", Accept: "application/json" } }
  );
  const categories = (await res.json()).data.items;
  ```
  {{< /tab >}}

  {{< tab name="PHP" >}}
  ```php
  $res = Http::withToken('<YOUR_TOKEN>')->acceptJson()
      ->get('https://console.intuizi.com/api/v2/analyses/reference/profile-attributes/categories');
  $categories = $res->json('data.items');
  ```
  {{< /tab >}}

{{< /tabs >}}

### Response

```json
{
  "status": "success",
  "code": 200,
  "message": "Resources fetched successfully.",
  "data": {
    "items": [
      { "value": 1, "text": "Auto" },
      { "value": 2, "text": "Finance" }
    ],
    "pagination": {
      "current_page": 1,
      "per_page": 500,
      "total": 2,
      "last_page": 1
    }
  }
}
```

## Get Profile Attributes Keys {#get-apiv2analysesreferenceprofile-attributeskeys}

`GET /api/v2/analyses/reference/profile-attributes/keys`

The second cascade level: the keys available under the chosen categories.
`value` is the key string a `profile_attributes` row's `key` takes and
`category_id` the category it belongs to, so one read tells you both which keys
exist and which category each is filed under. Paginated.

Pass `category_ids[]` to narrow the list to the category you picked - a key is
only valid on a row whose `category_id` matches.

### Query parameters

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `page` | integer | No | Page number (standard pagination). |
| `per_page` | integer | No | Items per page, capped at 500. |
| `search` | string | No | Optional free-text filter on the key or its label (case-insensitive contains). |
| `category_ids` | integer[] | No | Category ids to cascade from. Omit to list every key. |

{{< tabs >}}

  {{< tab name="cURL" >}}
  ```bash
  curl "https://console.intuizi.com/api/v2/analyses/reference/profile-attributes/keys?category_ids[]=1" \
    -H "Authorization: Bearer <YOUR_TOKEN>" \
    -H "Accept: application/json"
  ```
  {{< /tab >}}

  {{< tab name="Python" >}}
  ```python
  import requests

  res = requests.get(
      "https://console.intuizi.com/api/v2/analyses/reference/profile-attributes/keys",
      params={"category_ids[]": 1},
      headers={"Authorization": "Bearer <YOUR_TOKEN>", "Accept": "application/json"},
  )
  keys = res.json()["data"]["items"]
  ```
  {{< /tab >}}

  {{< tab name="JavaScript" >}}
  ```javascript
  const res = await fetch(
    "https://console.intuizi.com/api/v2/analyses/reference/profile-attributes/keys?category_ids[]=1",
    { headers: { Authorization: "Bearer <YOUR_TOKEN>", Accept: "application/json" } }
  );
  const keys = (await res.json()).data.items;
  ```
  {{< /tab >}}

  {{< tab name="PHP" >}}
  ```php
  $res = Http::withToken('<YOUR_TOKEN>')->acceptJson()
      ->get('https://console.intuizi.com/api/v2/analyses/reference/profile-attributes/keys', [
          'category_ids' => [1],
      ]);
  $keys = $res->json('data.items');
  ```
  {{< /tab >}}

{{< /tabs >}}

### Response

```json
{
  "status": "success",
  "code": 200,
  "message": "Resources fetched successfully.",
  "data": {
    "items": [
      { "value": "auto_body_style", "text": "auto_body_style", "category_id": 1 },
      { "value": "auto_intent", "text": "Auto Intent", "category_id": 1 }
    ],
    "pagination": {
      "current_page": 1,
      "per_page": 500,
      "total": 2,
      "last_page": 1
    }
  }
}
```

## Get Profile Attributes Values {#get-apiv2analysesreferenceprofile-attributesvalues}

`GET /api/v2/analyses/reference/profile-attributes/values`

The third cascade level: the values selectable for one category and key.
`value` is the id a `profile_attributes` row's `value_ids` takes, `raw_value` is
the value that is stored on the audience, and `category_id` / `key` echo the
pair the row belongs to. Paginated.

Pass both `category_ids[]` and `key` - a value is only valid on a row whose
`category_id` and `key` both match.

### Query parameters

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `page` | integer | No | Page number (standard pagination). |
| `per_page` | integer | No | Items per page, capped at 500. |
| `search` | string | No | Optional free-text filter on the value or its label (case-insensitive contains). |
| `category_ids` | integer[] | No | Category ids to cascade from. |
| `key` | string | No | The key to cascade from. |

{{< tabs >}}

  {{< tab name="cURL" >}}
  ```bash
  curl "https://console.intuizi.com/api/v2/analyses/reference/profile-attributes/values?category_ids[]=1&key=auto_intent" \
    -H "Authorization: Bearer <YOUR_TOKEN>" \
    -H "Accept: application/json"
  ```
  {{< /tab >}}

  {{< tab name="Python" >}}
  ```python
  import requests

  res = requests.get(
      "https://console.intuizi.com/api/v2/analyses/reference/profile-attributes/values",
      params={"category_ids[]": 1, "key": "auto_intent"},
      headers={"Authorization": "Bearer <YOUR_TOKEN>", "Accept": "application/json"},
  )
  values = res.json()["data"]["items"]
  ```
  {{< /tab >}}

  {{< tab name="JavaScript" >}}
  ```javascript
  const res = await fetch(
    "https://console.intuizi.com/api/v2/analyses/reference/profile-attributes/values?category_ids[]=1&key=auto_intent",
    { headers: { Authorization: "Bearer <YOUR_TOKEN>", Accept: "application/json" } }
  );
  const values = (await res.json()).data.items;
  ```
  {{< /tab >}}

  {{< tab name="PHP" >}}
  ```php
  $res = Http::withToken('<YOUR_TOKEN>')->acceptJson()
      ->get('https://console.intuizi.com/api/v2/analyses/reference/profile-attributes/values', [
          'category_ids' => [1],
          'key' => 'auto_intent',
      ]);
  $values = $res->json('data.items');
  ```
  {{< /tab >}}

{{< /tabs >}}

### Response

```json
{
  "status": "success",
  "code": 200,
  "message": "Resources fetched successfully.",
  "data": {
    "items": [
      { "value": 10, "text": "High", "raw_value": "high", "category_id": 1, "key": "auto_intent" },
      { "value": 11, "text": "Medium", "raw_value": "medium", "category_id": 1, "key": "auto_intent" },
      { "value": 12, "text": "Low", "raw_value": "low", "category_id": 1, "key": "auto_intent" }
    ],
    "pagination": {
      "current_page": 1,
      "per_page": 500,
      "total": 3,
      "last_page": 1
    }
  }
}
```

## Get Profile Attributes Recency Limits {#get-apiv2analysesreferenceprofile-attributesrecency-limits}

`GET /api/v2/analyses/reference/profile-attributes/recency-limits`

The delivered window a `ProfileAttributes` dataset's `start_date` and `end_date`
must fall inside. Profile attribute data is delivered quarterly, so the stored
window is expanded out to whole quarters - `start_date` to the first day of its
quarter and `end_date` to the last day of its quarter.

Read this before building the dataset and keep both dates between the two
inclusive `Y-m-d` bounds it returns; a date outside them is rejected with `422`.

### Query parameters

This read takes no parameters.

{{< tabs >}}

  {{< tab name="cURL" >}}
  ```bash
  curl "https://console.intuizi.com/api/v2/analyses/reference/profile-attributes/recency-limits" \
    -H "Authorization: Bearer <YOUR_TOKEN>" \
    -H "Accept: application/json"
  ```
  {{< /tab >}}

  {{< tab name="Python" >}}
  ```python
  import requests

  res = requests.get(
      "https://console.intuizi.com/api/v2/analyses/reference/profile-attributes/recency-limits",
      headers={"Authorization": "Bearer <YOUR_TOKEN>", "Accept": "application/json"},
  )
  limits = res.json()["data"][0]
  ```
  {{< /tab >}}

  {{< tab name="JavaScript" >}}
  ```javascript
  const res = await fetch(
    "https://console.intuizi.com/api/v2/analyses/reference/profile-attributes/recency-limits",
    { headers: { Authorization: "Bearer <YOUR_TOKEN>", Accept: "application/json" } }
  );
  const limits = (await res.json()).data[0];
  ```
  {{< /tab >}}

  {{< tab name="PHP" >}}
  ```php
  $res = Http::withToken('<YOUR_TOKEN>')->acceptJson()
      ->get('https://console.intuizi.com/api/v2/analyses/reference/profile-attributes/recency-limits');
  $limits = $res->json('data.0');
  ```
  {{< /tab >}}

{{< /tabs >}}

### Response

```json
{
  "status": "success",
  "code": 200,
  "message": "Resources fetched successfully.",
  "data": [
    { "start_limit": "2026-04-01", "end_limit": "2026-09-30" }
  ]
}
```
