# Meta

## Get the part registry

**get** `/v1/meta/parts`

Retrieves the part registry: every part type with its capability token,
interactivity, and schema, plus every server-enforced rule by name.

**Behavior**

- Static; it describes this API, not any chat.
- Intersect each part's `token` with a chat's announced `capabilities`
  (from `GET /v1/chats/{chat}`) to know which part types the customer's
  device can render. A composer must not offer payloads the device
  cannot support.

### Returns

- `PartRegistryResponse object { parts, rules }`

  The part registry: the union, its capability gates, and every enforced rule.

  - `parts: array of PartInfo`

    - `token: string`

      The capability-list token a device must announce, same value as `capability_token`. EMPTY means universal; not "unknown" and not "blocked": disable a type only when this is non-empty and the token is missing from the chat's `capabilities`.

    - `interactive: boolean`

      Whether the part renders as an interactive message (Apple's `interactiveData` family plus the payment, auth and app balloons).

    - `label: string`

      What a composer calls this type in front of a human. Served rather than hardcoded client-side so the name has one home.

    - `schema: unknown`

      This type's JSON Schema 2020-12: the same authority document `GET /v1/parts/{type}` publishes byte-verbatim, embedded here as JSON so one request equips a composer for every type.

    - `summary: string`

      One line describing what the customer sees, for a composer's type picker.

    - `type: string`

      The wire discriminator; `text`, `choices`, `list_picker`, …

    - `capability_token: optional string`

      The capability-list token a device must announce for this part to render. ABSENT means universal: disable a type only when this field is present and the token is missing from the chat's `capabilities`. Kept alongside `token`, which carries the same value: the long name shipped first and a client may already read it.

    - `degrade_note: optional string`

      What a customer sees when this part degrades, or why it never does. Present for every capability-gated part, and read together with `degrades_to`: a note WITHOUT `degrades_to` means the part is never substituted and the note says why (an unsupported send is refused, not rewritten); a note alongside `degrades_to` describes the substitution. An empty target list is never served: absence of `degrades_to` is the signal.

    - `degrades_to: optional array of string`

      The POSSIBLE part types this one can become under `degrade:"auto"` when its token is not announced, richest first. Informational, not device-resolved: which one a given customer gets depends on the rest of their announced capabilities, so preview the message against the chat for the answer a specific device would produce. Absent for universal parts, and for gated parts that are never substituted; `degrade_note` tells that story either way.

    - `device_scope: optional string`

      Which devices render this type, as prose from the OS-capability matrix; e.g. `iPhone, iPad` or `iPhone, iPad, Mac`.

    - `kit: optional string`

      Where this row is sourced in Apple's canonical documentation, as line references.

    - `min_ios: optional string`

      Minimum iOS/iPadOS version, e.g. `18.4`. Every type has one; AMB is an iOS-first channel, so this is always present.

    - `min_macos: optional string`

      Minimum macOS version. ABSENT means the type does not render on macOS AT ALL (the capability matrix's N/A), which is exactly what a lock reason needs to say; it is not "unknown".

    - `rules: optional array of string`

      Names of the entries in `rules` this type's validator applies, so a composer can show the bounds it is about to enforce without deciding which ones matter.

  - `rules: unknown`

    Every registered rule by its `x-cerebro-rule` name: the same names the part schemas carry.

### Example

```http
curl https://messages.api.linqapp.com/v1/meta/parts \
    -H "Authorization: Bearer $LINQ_AMB_API_KEY"
```

#### Response

```json
{
  "parts": [
    {
      "type": "text",
      "capability_token": "",
      "token": "",
      "label": "Text",
      "summary": "A plain message; `subject` renders bold.",
      "min_ios": "13.0",
      "min_macos": "10.15",
      "device_scope": "iPhone, iPad, Mac",
      "kit": "L1035",
      "rules": [
        "max_text_body_runes",
        "text_body_bmp_only"
      ],
      "interactive": false,
      "schema": {
        "title": "text",
        "type": "object"
      }
    }
  ],
  "rules": {
    "max_text_body_runes": {
      "kind": "bound",
      "limit": 2000
    },
    "text_body_bmp_only": {
      "kind": "semantic",
      "statement": "must contain only Basic Multilingual Plane characters"
    }
  }
}
```

## Domain Types

### Part Info

- `PartInfo object { token, interactive, label, 11 more }`

  One member of the sealed part union, described for a composer.

  - `token: string`

    The capability-list token a device must announce, same value as `capability_token`. EMPTY means universal; not "unknown" and not "blocked": disable a type only when this is non-empty and the token is missing from the chat's `capabilities`.

  - `interactive: boolean`

    Whether the part renders as an interactive message (Apple's `interactiveData` family plus the payment, auth and app balloons).

  - `label: string`

    What a composer calls this type in front of a human. Served rather than hardcoded client-side so the name has one home.

  - `schema: unknown`

    This type's JSON Schema 2020-12: the same authority document `GET /v1/parts/{type}` publishes byte-verbatim, embedded here as JSON so one request equips a composer for every type.

  - `summary: string`

    One line describing what the customer sees, for a composer's type picker.

  - `type: string`

    The wire discriminator; `text`, `choices`, `list_picker`, …

  - `capability_token: optional string`

    The capability-list token a device must announce for this part to render. ABSENT means universal: disable a type only when this field is present and the token is missing from the chat's `capabilities`. Kept alongside `token`, which carries the same value: the long name shipped first and a client may already read it.

  - `degrade_note: optional string`

    What a customer sees when this part degrades, or why it never does. Present for every capability-gated part, and read together with `degrades_to`: a note WITHOUT `degrades_to` means the part is never substituted and the note says why (an unsupported send is refused, not rewritten); a note alongside `degrades_to` describes the substitution. An empty target list is never served: absence of `degrades_to` is the signal.

  - `degrades_to: optional array of string`

    The POSSIBLE part types this one can become under `degrade:"auto"` when its token is not announced, richest first. Informational, not device-resolved: which one a given customer gets depends on the rest of their announced capabilities, so preview the message against the chat for the answer a specific device would produce. Absent for universal parts, and for gated parts that are never substituted; `degrade_note` tells that story either way.

  - `device_scope: optional string`

    Which devices render this type, as prose from the OS-capability matrix; e.g. `iPhone, iPad` or `iPhone, iPad, Mac`.

  - `kit: optional string`

    Where this row is sourced in Apple's canonical documentation, as line references.

  - `min_ios: optional string`

    Minimum iOS/iPadOS version, e.g. `18.4`. Every type has one; AMB is an iOS-first channel, so this is always present.

  - `min_macos: optional string`

    Minimum macOS version. ABSENT means the type does not render on macOS AT ALL (the capability matrix's N/A), which is exactly what a lock reason needs to say; it is not "unknown".

  - `rules: optional array of string`

    Names of the entries in `rules` this type's validator applies, so a composer can show the bounds it is about to enforce without deciding which ones matter.

### Part Registry Response

- `PartRegistryResponse object { parts, rules }`

  The part registry: the union, its capability gates, and every enforced rule.

  - `parts: array of PartInfo`

    - `token: string`

      The capability-list token a device must announce, same value as `capability_token`. EMPTY means universal; not "unknown" and not "blocked": disable a type only when this is non-empty and the token is missing from the chat's `capabilities`.

    - `interactive: boolean`

      Whether the part renders as an interactive message (Apple's `interactiveData` family plus the payment, auth and app balloons).

    - `label: string`

      What a composer calls this type in front of a human. Served rather than hardcoded client-side so the name has one home.

    - `schema: unknown`

      This type's JSON Schema 2020-12: the same authority document `GET /v1/parts/{type}` publishes byte-verbatim, embedded here as JSON so one request equips a composer for every type.

    - `summary: string`

      One line describing what the customer sees, for a composer's type picker.

    - `type: string`

      The wire discriminator; `text`, `choices`, `list_picker`, …

    - `capability_token: optional string`

      The capability-list token a device must announce for this part to render. ABSENT means universal: disable a type only when this field is present and the token is missing from the chat's `capabilities`. Kept alongside `token`, which carries the same value: the long name shipped first and a client may already read it.

    - `degrade_note: optional string`

      What a customer sees when this part degrades, or why it never does. Present for every capability-gated part, and read together with `degrades_to`: a note WITHOUT `degrades_to` means the part is never substituted and the note says why (an unsupported send is refused, not rewritten); a note alongside `degrades_to` describes the substitution. An empty target list is never served: absence of `degrades_to` is the signal.

    - `degrades_to: optional array of string`

      The POSSIBLE part types this one can become under `degrade:"auto"` when its token is not announced, richest first. Informational, not device-resolved: which one a given customer gets depends on the rest of their announced capabilities, so preview the message against the chat for the answer a specific device would produce. Absent for universal parts, and for gated parts that are never substituted; `degrade_note` tells that story either way.

    - `device_scope: optional string`

      Which devices render this type, as prose from the OS-capability matrix; e.g. `iPhone, iPad` or `iPhone, iPad, Mac`.

    - `kit: optional string`

      Where this row is sourced in Apple's canonical documentation, as line references.

    - `min_ios: optional string`

      Minimum iOS/iPadOS version, e.g. `18.4`. Every type has one; AMB is an iOS-first channel, so this is always present.

    - `min_macos: optional string`

      Minimum macOS version. ABSENT means the type does not render on macOS AT ALL (the capability matrix's N/A), which is exactly what a lock reason needs to say; it is not "unknown".

    - `rules: optional array of string`

      Names of the entries in `rules` this type's validator applies, so a composer can show the bounds it is about to enforce without deciding which ones matter.

  - `rules: unknown`

    Every registered rule by its `x-cerebro-rule` name: the same names the part schemas carry.

### Part Rule

- `PartRule object { kind, limit, statement }`

  One registered constraint the strict JSON-Schema subset cannot express.

  - `kind: "bound" or "semantic"`

    `bound` carries `limit`; `semantic` carries `statement`.

    - `"bound"`

    - `"semantic"`

  - `limit: optional number`

    The enforced numeric limit, on a `bound` rule.

  - `statement: optional string`

    The human-readable rule, on a `semantic` rule.
