> For the complete documentation index, see [llms.txt](https://docs.nfh.global/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nfh.global/product-documentation/products/discovr/usage.md).

# Usage

How to discover resources across published catalogues using the Beckn Protocol v2.0.

How to discover resources across published catalogues using the Beckn Protocol v2.0.

## Request Format

```json
{
  "context": {
    "version": "2.0.0",
    "action": "discover",
    "messageId": "<uuid>",
    "transactionId": "<uuid>",
    "timestamp": "<ISO 8601>",
    "bapId": "<your-identifier>",
    "bapUri": "<your-callback-url>",
    "networkId": "<network-id>"
  },
  "message": {
    "intent": { ... }
  }
}
```

| Field            | Description                                                                                                                                                                                                                                     |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `action`         | Always `discover` for a discovery request                                                                                                                                                                                                       |
| `messageId`      | UUID correlating this request with its `on_discover` response                                                                                                                                                                                   |
| `transactionId`  | UUID for the end-to-end interaction                                                                                                                                                                                                             |
| `bapId`          | Your consumer identifier                                                                                                                                                                                                                        |
| `bapUri`         | Your callback URL — DISCOVR delivers results here via `POST /on_discover`                                                                                                                                                                       |
| `networkId`      | The network to search within. Optional — omit to search all indexed networks. On ONIX 1.8.0+, the calling BAP must be authorised for this network in the registry (see [Network scoping and authorization](#network-scoping-and-authorization)) |
| `message.intent` | The search criteria — see [Examples](/product-documentation/products/discovr/examples.md)                                                                                                                                                       |

## Response Format

Results are delivered asynchronously to your `bapUri` as an `on_discover` callback:

```json
{
  "context": {
    "action": "on_discover",
    "messageId": "...",
    "transactionId": "...",
    "bapId": "...",
    "timestamp": "..."
  },
  "message": {
    "catalogs": [
      {
        "id": "CAT-GROCERY-001",
        "descriptor": { "name": "FreshMart Grocery Catalog" },
        "resources": [
          {
            "id": "ITEM-BRU-COFFEE",
            "descriptor": { "name": "Bru Gold Instant Coffee" },
            "rating": { "ratingValue": 4.1, "ratingCount": 18200 },
            "resourceAttributes": { "@type": "GroceryItem", "brand": "Bru" }
          }
        ],
        "offers": [
          {
            "id": "OFFER-COFFEE-BUNDLE",
            "descriptor": { "name": "Coffee Lovers Bundle" },
            "resourceIds": ["ITEM-BRU-COFFEE", "ITEM-NESCAFE"],
            "offerAttributes": {
              "priceSpecification": { "price": 255, "discount": "15%" }
            }
          }
        ]
      }
    ]
  }
}
```

The response includes only catalogues, resources, and offers that match your query. Empty results return `"catalogs": []`. Your service correlates this callback with the original request via the shared `context.messageId`.

## Network scoping and authorization

A discover request may set `context.networkId` to scope results to a single network. When it is omitted, DISCOVR searches across all networks the instance indexes.

**Authorization (ONIX 1.8.0+).** When the discover service is fronted by ONIX **1.8.0 or later**, network-scoped discovery is authorization-checked at the signature-validation layer. If a request sets `context.networkId`, ONIX resolves the caller's validation key from the registry (DeDi) **scoped to that network** — the lookup succeeds only if the network is listed in the calling subscriber's `network_memberships`. If it is not, the request is rejected with an `HTTP 401` NACK carrying `error.code: "Unauthorized"`. The values below are just an example:

```json
{
  "message": {
    "status": "NACK",
    "messageId": "469bfce5-ada9-4c9a-bb64-99bf3c100702",
    "error": {
      "code": "Unauthorized",
      "message": "Signature Validation Error: failed to validate Authorization: failed to get validation key: failed to lookup registry: context.network_id \"test/v1.5.0-rc5\" is not in network_memberships of subscriber \"beckn.bap.dev\""
    }
  }
}
```

Requests that do not set `context.networkId` are not network-scope-checked.

> **Migration note — before upgrading a discover instance to ONIX 1.8.0.** A BAP that uses network-scoped discovery (`context.networkId`) must have that network listed in its subscriber `network_memberships` in the registry. Once the fronting ONIX is on 1.8.0, scoped requests from a BAP that is not a member of the requested network will fail signature validation with the `Unauthorized` error above. Notify affected client (BAP) instances ahead of the upgrade so their registry memberships are in place.

## Filtering by active and validity status

By default, DISCOVR returns only catalogs that are **active** and **currently valid** — inactive catalogs and catalogs outside their validity window are hidden. You can change this per request with two optional query parameters on `POST /discover`:

```
POST /discover?active=false&validity=false
```

| Parameter  | Values            | Meaning                                                                                                                                                                |
| ---------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `active`   | `true` \| `false` | `true` (default) returns only catalogs whose `isActive` is not explicitly `false`. `false` returns **only** catalogs explicitly marked inactive.                       |
| `validity` | `true` \| `false` | `true` (default) returns only catalogs inside their validity window. `false` returns **only** catalogs that are provably **out of window** (expired or not yet valid). |

**How to retrieve expired or inactive catalogs**

* Expired / not-yet-valid catalogs: `POST /discover?validity=false`
* Inactive catalogs: `POST /discover?active=false`
* Both: `POST /discover?active=false&validity=false`

**Semantics (null-safe).** A catalog with no `isActive` field counts as active; a catalog with no, open-ended, or unparseable `validity` counts as valid. `validity` bounds (`startDate` / `endDate`) are inclusive. When a parameter is omitted, the deployment default applies (both default to `true`, configurable via `DISCOVERY_FILTER_ACTIVE_CATALOG` and `DISCOVERY_FILTER_VALID_CATALOGS`).

> **Note.** The `active` / `validity` filters are applied on the structured query engines (JSONPath, spatial, and Elasticsearch text). They are **not** applied on the natural-language (NLWeb) text path — if you need the guarantee on a text query, use the Elasticsearch text engine.

## Synchronous Acknowledgement

When DISCOVR accepts the request, it returns an `ACK` synchronously:

```json
{ "message": { "status": "ACK", "messageId": "<uuid>" } }
```

If the request is invalid, it returns a `NACK`:

```json
{
  "message": {
    "status": "NACK",
    "messageId": "<uuid>",
    "error": {
      "code": "SCH_SCHEMA_VALIDATION_FAILED",
      "message": "context: must have required property 'transactionId'"
    }
  }
}
```

Error `code` values are drawn from the canonical Beckn v2.0 `ErrorCode` enum. The codes DISCOVR returns on a synchronous `NACK`:

| HTTP | Error Code                     | Meaning                                                        |
| ---- | ------------------------------ | -------------------------------------------------------------- |
| 400  | `SCH_INVALID_JSON`             | Request body is not valid JSON                                 |
| 400  | `SCH_SCHEMA_VALIDATION_FAILED` | Request doesn't match the expected schema                      |
| 400  | `CTX_MISSING_FIELD`            | A required `context` field is missing                          |
| 400  | `CTX_INVALID_FIELD`            | A `context` field has an invalid value (e.g. malformed intent) |
| 401  | `AUT_SIGNATURE_MISSING`        | `Authorization` header is absent                               |
| 401  | `AUT_SIGNATURE_INVALID`        | The request signature could not be verified                    |
| 401  | `AUT_SUBSCRIBER_NOT_FOUND`     | Signing subscriber is not registered                           |
| 500  | `NET_INTERNAL_ERROR`           | Unexpected server failure                                      |

> Auth failures return `401` (never `400`) with an `AUT_*` code. In the standard topology DISCOVR is fronted by ONIX, which performs auth validation and returns these responses.

## API Reference

| Operation                           | Method | Endpoint               | Action        |
| ----------------------------------- | ------ | ---------------------- | ------------- |
| **Discover resources**              | POST   | `/discover`            | `discover`    |
| **Receive results** (your endpoint) | POST   | `<bapUri>/on_discover` | `on_discover` |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.nfh.global/product-documentation/products/discovr/usage.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
