# Search

Discover related records across several resource types.

Canonical HTML: https://developer.shelfcycle.com/guides/search

Existing connections can use search to discover related ShelfCycle records across several resource types before choosing an exact detail endpoint.

Search remains available for existing connections. For new record binding, use [Entity Resolution](/guides/entity-resolution) when the workflow needs one stable ID, [Tags](/guides/tags) for exact organization groupings, [Product Directory](/guides/product-directory) for regulatory or name-based product discovery, or a typed finder when exact filters are already available.

## Endpoint

```text
GET /search
```

Required scope:

```text
search:read
```

Query parameters:

| Parameter | Meaning |
| --- | --- |
| `q` | Required search string. Minimum 2 characters. |
| `types` | Optional comma list: customer, supplier, contact, product, order, purchase_order, location. |
| `limit` | Optional result count from 1 to 20. Default is 10. |

Unknown query parameters are rejected. Use `types`, not `type`. Validation errors can return repair metadata such as `suggestedAction: "replace_param"` and `validValues.types` so clients can correct the next request without guessing.

## Request

```bash
curl "$SHELFCYCLE_API_BASE_URL/search?q=Northstar&types=customer,contact,purchase_order&limit=10" \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
  -H "X-ShelfCycle-Client: Email notes automation"
```

## Response

```json
{
  "data": [
    {
      "type": "contact",
      "id": "contact-id",
      "displayName": "Jordan Buyer",
      "subtitle": "Northstar Chemical · jordan@example.com · President",
      "url": "https://app.shelfcycle.com/org-northstar/customers/customer-id/contacts",
      "archived": false,
      "matchedFields": [
        { "field": "email", "label": "Email", "value": "jordan@example.com" },
        { "field": "parent.name", "label": "Customer", "value": "Northstar Chemical" }
      ],
      "parent": { "type": "customer", "id": "customer-id", "displayName": "Northstar Chemical" }
    }
  ],
  "meta": {
    "requestId": "request-id",
    "limit": 10,
    "types": ["customer", "contact", "purchase_order"],
    "rankingIsContractual": false,
    "truncated": false,
    "durationMs": 24
  }
}
```

`matchedFields` explains why a card matched. Use it before selecting the exact `{type,id}` for a write.

> **Information**: Ranking is useful but not contractual. If meta.truncated is true, narrow the query before writing.

## What search does not return

Search cards never include money, line items, costs, attached files, inventory, lots, margin, accounting, or arbitrary hidden fields. Use exact detail or parent-scoped document endpoints after the workflow selects one id.

## Next step after search

Use the selected card type to choose a detail endpoint:

```text
customer        GET /customers/{id}
supplier        GET /suppliers/{id}
contact         GET /contacts/{id}
product         GET /products/{id}
order           GET /orders/{id}
purchase_order  GET /purchase-orders/{id}
location        GET /customers/{id}/locations/{locationId}
documents       GET /{customers,suppliers,products}/{id}/documents
```

For typed lookup before detail, use finder endpoints such as `GET /customers`, `GET /products`, `GET /orders`, or `GET /purchase-orders`. Finders require narrowing criteria and are covered in the Finders guide.
