Usage
How to discover resources across published catalogues using the Beckn Protocol v2.0.
Request Format
{ "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) |
message.intent | The search criteria — see Examples |
Response Format
Results are delivered asynchronously to your bapUri as an on_discover callback:
{ "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:
{ "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:
{ "message": { "status": "ACK", "messageId": "<uuid>" } }
If the request is invalid, it returns a NACK:
{ "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 |