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

# Find a product’s filings and files by class or coverage

> Learn how product profiles, shared types and tags fit together, then list the filings and files that concern a business class, configuration or coverage part.

A product in the catalog can have hundreds of filings and thousands of files: rate manuals,
rule pages, forms and memos across many states. Most questions concern one slice of that
material, such as one business class (“what has this carrier filed about bakeries?”), one
coverage configuration or one coverage part. This guide shows how the API organizes a
product’s material into those slices, and how to list the filings and files for one of them
without reading everything.

## How the pieces fit together

Four parts work together:

| Part | What it is | Example |
| - | - | - |
| **Type** | A shared definition with named **fields**. Each field has **options**: its allowed values, each with a stable key and a label. | Type `example-carrier.bop-operation` has field `classCode`, whose options include `10101` “Bakeries” and `10103` “Clothing stores”. |
| **Profile** | A product’s description: customer type, package or monoline, target market, and its **primary cuts**. A cut points at a field, saying “this product’s material is organized by this field”. | The example product’s cuts are class code, coverage configuration and coverage part. |
| **Resource** | A filing or file associated with the product, with the states and components (rate manual, form, filing) it is used for. | A rate manual filed in Ohio. |
| **Tag** | A pointer from a resource to an option, a field or a whole type, meaning “this resource concerns that”. | A memo announcing a new bakery class is tagged with option `10101`. A manual containing the full class table is tagged with the `classCode` field itself. |

```mermaid theme={null}
flowchart LR
  P[Product] -- profile --> C[Primary cuts]
  C -- point to --> F[Field, e.g. classCode]
  F -- has --> O[Options, e.g. 10101 Bakeries]
  P -- associated --> R[Resources: filings and files]
  R -- tagged with --> O
  R -- or tagged with --> F
```

So the profile tells you which ways of slicing a product’s material make sense, the type
tells you the slices that exist (for example, every class code), and tags tell you which
filings and files belong to each slice.

Types here are product taxonomy definitions, separate from the NAIC lines of business at
`/insurance/insurance-types`.

### Refs: one address for everything

Cuts and tags use the same address format, a **ref**. A ref names a type, optionally narrowed
to one field, optionally narrowed to one option:

| Ref | Points at |
| - | - |
| `/insurance/types/example-carrier.bop-operation` | The whole type |
| `/insurance/types/example-carrier.bop-operation#/fields/classCode` | The class-code field: class codes in general |
| `/insurance/types/example-carrier.bop-operation#/fields/classCode/options/10101` | One option: class `10101`, Bakeries |

The part before `#` is the type’s address; the part after `#` is a path inside the type’s
definition. Codes stay within their carrier’s type: one carrier’s class `10101` is unrelated
to another carrier’s `10101`, because their refs differ.

### Access

Reading a profile or a product’s resources needs an Effective API plan that covers the
product, or the state you filter on; otherwise the response is 403 `plan_required`. Type
definitions and target-market choices are free to read. Effective curates profiles, types and
tags; changing them requires Super Admin credentials.

The examples below use a fictional carrier, product and class codes. Replace placeholders such
as `{productId}` with the IDs the API returns.

## 1. Find the product

Search the catalog by name:

```bash theme={null}
curl --request GET \
  --url "https://api.canary.effectiveai.app/api/v2/insurance/products?name=Example%20Business&limit=5" \
  --header "Authorization: Bearer $EFFECTIVE_API_KEY"
```

```json Response (abbreviated) theme={null}
{
  "products": [
    {
      "id": "{productId}",
      "name": "Example Business Owner's Policy",
      "type": "bop",
      "admitted": true,
      "availabilitySummary": { "states": ["AZ", "CO", "OH"], "stateCount": 3 }
    }
  ],
  "nextCursor": null
}
```

Keep the `id`; every later request uses it. See
[Research a carrier, group, or MGA](/guides/carrier-filings#find-related-catalog-products)
for other ways to find products.

## 2. Read the profile and its cuts

The profile tells you how this product’s material is organized. Add `expand=primaryCuts` so the
response also includes the type definition behind each cut, with every option:

```bash theme={null}
curl --request GET \
  --url "https://api.canary.effectiveai.app/api/v2/insurance/products/{productId}/profile?expand=primaryCuts" \
  --header "Authorization: Bearer $EFFECTIVE_API_KEY"
```

```json Response (abbreviated) theme={null}
{
  "customerType": "BUSINESS",
  "structure": "PACKAGE",
  "targetMarket": {
    "ref": "/insurance/types/business-buyer#/fields/market/options/small-business"
  },
  "primaryCuts": [
    { "ref": "/insurance/types/example-carrier.bop-operation#/fields/classCode" },
    { "ref": "/insurance/types/bop.coverage-configuration#/fields/configuration" },
    { "ref": "/insurance/types/bop.coverage-part#/fields/coveragePart" }
  ],
  "definitions": [
    {
      "id": "example-carrier.bop-operation",
      "label": "Example Carrier BOP Business Class",
      "revision": 1,
      "fields": {
        "classCode": {
          "label": "Business class",
          "type": "string",
          "revision": 1,
          "options": {
            "10101": { "label": "Bakeries" },
            "10103": {
              "label": "Clothing stores",
              "description": "In the carrier's earlier program, this code was Apparel and accessory stores."
            }
          }
        }
      }
    },
    {
      "id": "bop.coverage-configuration",
      "label": "BOP Coverage Configuration",
      "revision": 1,
      "fields": {
        "configuration": {
          "label": "Coverage configuration",
          "type": "string",
          "revision": 1,
          "options": {
            "package": {
              "label": "Property and liability",
              "description": "A configuration containing property and liability coverage."
            },
            "property-only": {
              "label": "Property only",
              "description": "A configuration containing property coverage without the liability section."
            }
          }
        }
      }
    }
  ]
}
```

How to read it:

* `customerType` and `structure` say this is a business package policy.
* `targetMarket` is a ref to an option of the shared `business-buyer` type: small businesses.
* `primaryCuts` lists the three fields this product is organized by. The first is the
  carrier’s own class-code field; the other two are shared business owner’s policy fields that
  every carrier’s BOP can use.
* `definitions` holds the full type behind each cut. To list every class code, read
  `definitions[].fields.classCode.options`: each key is the class code, and `label` is its name.
  A `description` records extra facts, such as a code that meant something else in an earlier
  program.

Without `expand`, the response has only the refs. A product without a profile returns `null`
fields and no cuts.

## 3. List the filings and files for one option

Pick an option from the profile, build its ref, and pass it as `ref`. URL-encode the ref, so
`#` becomes `%23` and `/` becomes `%2F`. This lists the filings and files tagged with class
`10101`, Bakeries:

```bash theme={null}
curl --request GET \
  --url "https://api.canary.effectiveai.app/api/v2/insurance/products/{productId}/resources?ref=%2Finsurance%2Ftypes%2Fexample-carrier.bop-operation%23%2Ffields%2FclassCode%2Foptions%2F10101&limit=2" \
  --header "Authorization: Bearer $EFFECTIVE_API_KEY"
```

```json Response (first item) theme={null}
{
  "resources": [
    {
      "id": "filing:{filingId}",
      "kind": "filing",
      "sourceId": "{filingId}",
      "name": "EXMP-000000001",
      "associations": [
        {
          "state": "OH",
          "component": "filing",
          "source": "serff",
          "url": null,
          "filing": {
            "id": "{filingId}",
            "trackingNumber": "EXMP-000000001"
          },
          "form": null
        }
      ],
      "tags": [
        { "ref": "/insurance/types/example-carrier.bop-operation#/fields/classCode/options/10101" }
      ],
      "match": "direct"
    }
  ],
  "nextCursor": "{nextCursor}"
}
```

This filing, an Ohio filing with tracking number `EXMP-000000001`, is tagged with class
`10101`, so it matched directly. Each resource carries:

* `id`: the resource ID, `filing:{id}` or `file:{id}`. Pass it unchanged to
  `GET /insurance/products/{productId}/resources/{resourceId}` to read one resource again.
* `kind` and `sourceId`: whether it is a filing or a file, and its ID in the filing and file
  APIs.
* `associations`: where the product uses it: the `state`, the `component` (`filing`,
  `rate_manual`, `uw_manual` or `form`), the filing it came from, and form details for forms.
  A file used in several states appears once with one association per state.
* `tags`: every ref the resource is tagged with, in order.
* `match`: why it matched your `ref` (see the next step). Requests without `ref` return
  `match: null`.

## 4. Include material about the whole cut

By default the match is exact: asking for class `10101` returns only resources tagged with
`10101`. Some of the most useful material is tagged more broadly. A rate manual’s classification
table covers every class, so it is tagged with the `classCode` field rather than with each code.

Add `includeGeneral=true` to include resources tagged with the enclosing field or type. Add
`state` to keep only one state’s associations:

```bash theme={null}
curl --request GET \
  --url "https://api.canary.effectiveai.app/api/v2/insurance/products/{productId}/resources?ref=%2Finsurance%2Ftypes%2Fexample-carrier.bop-operation%23%2Ffields%2FclassCode%2Foptions%2F10101&includeGeneral=true&state=OH&limit=3" \
  --header "Authorization: Bearer $EFFECTIVE_API_KEY"
```

```json Response (first item) theme={null}
{
  "resources": [
    {
      "id": "file:{fileId}",
      "kind": "file",
      "sourceId": "{fileId}",
      "name": "Example BOP Rate Manual.pdf",
      "associations": [
        {
          "state": "OH",
          "component": "rate_manual",
          "source": "serff",
          "url": null,
          "filing": {
            "id": "{filingId}",
            "trackingNumber": "EXMP-000000002"
          },
          "form": null
        }
      ],
      "tags": [{ "ref": "/insurance/types/example-carrier.bop-operation#/fields/classCode" }],
      "match": "general"
    }
  ],
  "nextCursor": "{nextCursor}"
}
```

This rate manual isn’t about bakeries specifically, but it is about class codes in general, so
it comes back with `match: "general"`. Resources tagged with `10101` itself come back as
`direct`, and each resource appears once. Resources tagged only with a different class, such as
`10103`, never appear.

## 5. Look up a ref you found elsewhere

Tags on a resource are refs. To turn one into a readable name, fetch its type (the part before
`#`) and follow the path after `#`. For the tag
`/insurance/types/example-carrier.bop-operation#/fields/classCode/options/10103`:

```bash theme={null}
curl --request GET \
  --url "https://api.canary.effectiveai.app/api/v2/insurance/types/example-carrier.bop-operation" \
  --header "Authorization: Bearer $EFFECTIVE_API_KEY"
```

```json Response (abbreviated) theme={null}
{
  "id": "example-carrier.bop-operation",
  "label": "Example Carrier BOP Business Class",
  "revision": 1,
  "fields": {
    "classCode": {
      "label": "Business class",
      "type": "string",
      "revision": 1,
      "options": {
        "10101": { "label": "Bakeries" },
        "10103": {
          "label": "Clothing stores",
          "description": "In the carrier's earlier program, this code was Apparel and accessory stores."
        }
      }
    }
  }
}
```

The path `/fields/classCode/options/10103` leads to `fields.classCode.options["10103"]`, so the
tag means class `10103`, Clothing stores. Send only the type’s address to this endpoint; the
part after `#` is resolved by you, not by the server. (When you pass a whole ref as the `ref`
filter in steps 3 and 4, send all of it, URL-encoded.)

If you already read the profile with `expand=primaryCuts`, its `definitions` contain the same
types, and you don’t need this request. `GET /insurance/types` lists every type. Labels and
descriptions can be corrected over time; type IDs, field keys and option keys never change, so
a ref you store keeps working.

## 6. Open what you found

A resource points at the filing or file; read it with the filing and file APIs. For a filing,
list its documents with `GET /insurance/filings/{sourceId}/files`. For a file, read its text
with `GET /files/{sourceId}/text`. See
[Read and cite document evidence](/guides/read-filing-documents) for reading, resuming and
citing. Listing a resource doesn’t grant access beyond what those APIs already allow.

## Interpret tags carefully

* **A tag means relevant, not eligible.** A filing tagged with a class may introduce it,
  restrict it, exclude it or describe its history. A tag doesn’t say the class is accepted, or
  that the product is sold in a state.
* **No tag doesn’t mean not relevant.** Effective curates tags and they can be incomplete. An
  empty result means no resource carries that tag; try `includeGeneral=true`, or read the
  product’s manuals.
* **Cuts organize material; they aren’t eligibility rules.** A configuration or class listed in
  the profile isn’t necessarily available in every state or for every transaction.

## Continue and recover

Lists default to 50 resources; `limit` accepts 1–200. To get the next page, repeat the request
with the same `ref`, `includeGeneral`, `state` and `limit`, plus `cursor` set to `nextCursor`.
Cursors expire after 24 hours; after `invalid_cursor`, start again without one. Results reflect
current data, not a snapshot, and there is no total count.

* `invalid_request` (400): the `ref` isn’t valid. Either it isn’t spelled exactly as the API
  returns refs, or it names a type, field or option that doesn’t exist. Copy refs from the
  profile or from tags, and URL-encode them.
* `invalid_id` (400): the product ID is malformed. Copy it from `GET /insurance/products`.
* `plan_required` (403): your plan doesn’t cover the product, or the state you filtered on.
  With a plan covering only some states, lists include only those states’ associations.
* `not_found` (404): the product or type doesn’t exist, or a resource is no longer associated
  with the product, or is associated only with states your plan doesn’t cover.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.