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

# List preferences

> Every `(target, medium)` known for this recipient, each with the state a send would **actually** act on.

`state.enabled` is the **resolved** decision — the same answer the delivery path computes — not a raw stored row. Resolution walks, in order:

1. the recipient's rule for the exact target,
2. the recipient's `topic: any` rule for the channel/event,
3. the project's rule for the exact target,
4. the project's `topic: any` rule,
5. the medium's **default**.

**The default is per medium:** `in_app` delivers, every other medium does not. A `topic: none` target never takes an `any` rule.

The response covers every target in the project catalog **plus** any target this recipient has a rule of their own for, across the active mediums (`in_app` and `email`). So a recipient can have an entry for a `(target, medium)` you never cataloged — if they have an explicit rule for it, it is live, and this reports it.

Each `state` carries:

-   `enabled` — whether a send to this `(target, medium)` would deliver.
-   `inherited` — `true` when the recipient has no rule of their own for this exact `(target, medium)`; the value came from elsewhere in the cascade. `false` means they set it explicitly.
-   `cataloged` — whether a project-level rule exists for this exact `(target, medium)`. This is **context, not a gate**: an explicit recipient rule on an uncataloged pair still delivers, and `in_app` delivers by default with no catalog entry at all. Use it to decide what to render, never to predict delivery — `enabled` is the answer.

Every `(target, medium)` known for this recipient, each **resolved** — `state.enabled` is what a send would actually do, not a raw stored row. To manage project preferences (the catalog), use the [Project Preferences](/api-reference/endpoint/preferences/list-project-preferences) endpoints or **Bodhveda Console > Preferences**.

💡 You should show these preferences on your "Notification settings" screen where the recipient can see their current preferences and update them with [set preference](/api-reference/endpoint/recipients/preferences/set-preference).

* `inherited: false` means the recipient **has** explicitly overridden this `(target, medium)`; `true` means the value came from elsewhere in the [cascade](/docs/concepts/preferences#how-a-preference-resolves) (a `topic: any` rule, the catalog, or the medium's default).
* `cataloged: false` means your project has no rule declared for that exact `(target, medium)`. It is **not** a reason to treat the pair as unavailable — in-app delivers by default, and a recipient's own rule sends email regardless. It tells you what you declared, not what happens; `enabled` tells you what happens.

<Note>
  The response includes entries for `(target, medium)` pairs you never cataloged, whenever they resolve to something a recipient can act on. That is deliberate: if a recipient has a rule for it, or a medium delivers by default, hiding it would show them a setting that disagrees with their inbox.
</Note>


## OpenAPI

````yaml GET /recipients/{recipient_id}/preferences
openapi: 3.0.3
info:
  title: Bodhveda Notifications API
  version: '1.0'
  description: API for sending notifications to recipients or broadcasting to all.
servers: []
security: []
paths:
  /recipients/{recipient_id}/preferences:
    get:
      tags:
        - Preferences
      summary: List preferences for a recipient
      description: >-
        Every `(target, medium)` known for this recipient, each with the state a
        send would **actually** act on.


        `state.enabled` is the **resolved** decision — the same answer the
        delivery path computes — not a raw stored row. Resolution walks, in
        order:


        1. the recipient's rule for the exact target,

        2. the recipient's `topic: any` rule for the channel/event,

        3. the project's rule for the exact target,

        4. the project's `topic: any` rule,

        5. the medium's **default**.


        **The default is per medium:** `in_app` delivers, every other medium
        does not. A `topic: none` target never takes an `any` rule.


        The response covers every target in the project catalog **plus** any
        target this recipient has a rule of their own for, across the active
        mediums (`in_app` and `email`). So a recipient can have an entry for a
        `(target, medium)` you never cataloged — if they have an explicit rule
        for it, it is live, and this reports it.


        Each `state` carries:


        -   `enabled` — whether a send to this `(target, medium)` would deliver.

        -   `inherited` — `true` when the recipient has no rule of their own for
        this exact `(target, medium)`; the value came from elsewhere in the
        cascade. `false` means they set it explicitly.

        -   `cataloged` — whether a project-level rule exists for this exact
        `(target, medium)`. This is **context, not a gate**: an explicit
        recipient rule on an uncataloged pair still delivers, and `in_app`
        delivers by default with no catalog entry at all. Use it to decide what
        to render, never to predict delivery — `enabled` is the answer.
      operationId: listRecipientPreferences
      parameters:
        - name: recipient_id
          in: path
          required: true
          schema:
            type: string
          description: The unique identifier of the recipient.
      responses:
        '200':
          description: List of recipient's resolved preferences.
          content:
            application/json:
              examples:
                Preferences:
                  summary: Preferences Response
                  value:
                    data:
                      preferences:
                        - target:
                            channel: posts
                            topic: any
                            event: new_comment
                            medium: in_app
                            label: Comments on your posts
                          state:
                            enabled: true
                            inherited: true
                            cataloged: true
                        - target:
                            channel: announcements
                            topic: none
                            event: new_feature
                            medium: email
                            label: Product Announcements
                          state:
                            enabled: false
                            inherited: false
                            cataloged: true
                        - target:
                            channel: announcements
                            topic: none
                            event: new_feature
                            medium: in_app
                          state:
                            enabled: true
                            inherited: true
                            cataloged: false
      security:
        - BearerAuthWithAPIKeyWithEitherScope: []
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |-
            curl https://api.bodhveda.com/recipients/recipient_123/preferences \
              -H "Authorization: Bearer bv_xxxxxxxxx" 
        - lang: javascript
          label: JavaScript
          source: >-
            import { Bodhveda } from "@bodhveda/js";


            const bodhveda = new Bodhveda("bv_xxxxxxxxx");


            const { preferences } = await
            bodhveda.recipients.preferences.list("recipient_123");
        - lang: go
          label: Go
          source: |-
            import (
                "context"

                bodhveda "github.com/MudgalLabs/bodhveda/sdk/go"
            )

            ctx := context.Background()
            client := bodhveda.NewClient("bv_xxxxxxxxx", nil)

            res, _ := client.Recipients.Preferences.List(ctx, "recipient_123")
            // res.Preferences
        - lang: jsx
          label: React
          source: >-
            import { usePreferences } from "@bodhveda/react";


            // Requires a <BodhvedaProvider recipientID="recipient_123"> higher
            in the tree.

            function Preferences() {
                const { data, isLoading } = usePreferences();
                if (isLoading) return null;
                return <PreferenceList items={data.preferences} />;
            }
components:
  securitySchemes:
    BearerAuthWithAPIKeyWithEitherScope:
      type: http
      scheme: bearer
      bearerFormat: APIKey
      description: >-
        Bearer authentication header of the form `Bearer bv_xxxxxxxxx`, where
        `bv_xxxxxxxxx` is your **API Key** with `Full access` or `Recipient
        acess` scope.

````