For the complete documentation index, see llms.txt. This page is also available as Markdown.

Migrating from Beckn protocol version 1 to version 2

A readiness checklist for moving a Beckn network participant from protocol v1 to v2 — covering DEDI registry setup, protocol and schema readiness, ONIX configuration, and business application migratio

Executive Summary

Moving a Beckn network from v1 to v2 is not just a payload rename. V2 introduces improved identity and discovery, a JSON-LD-based protocol contract, and changes to adapter configuration — and it also touches how the business application connects to the network. This guide is a shared readiness checklist for that move, written for network participants, network facilitator organizations, and business application teams who need to align before implementation starts.

It walks through what a participant must get right, in the order it typically comes up: registering identity on the DEDI registry, meeting the v2 protocol and schema requirements, configuring ONIX correctly, and planning the business application's migration.

1. DEDI registry and participant records

The v2 migration path does not depend on a separate gateway. Instead, trust and participant discovery are established through the DEDI registry and its participant records.

DEDI registry readiness

Register on the DEDI registry before starting any other DEDI-dependent step below. Registration involves four steps:

  1. Namespace creation — Create and verify the participant's namespace by proving domain ownership. This establishes the root of trust for everything published under it.

  2. Registry publication — Add a registry under that namespace, following the NFH fabric subscriber schema, to list Beckn subscriber details.

  3. Subscriber record creation — Publish subscriber records for each participant, including callback URL, network role (consumer/provider node, etc.), domain code, and public key.

  4. ONIX interaction — Confirm that ONIX automatically resolves subscriber details (keys, roles, callback URLs) during network interactions. No additional registry API integration is required on the application side.

Reference

2. Protocol and schema readiness

For a new v1-to-v2 migration, start by creating the domain-specific schema, if it does not exist already, before anything else in this section — ONIX's validator has nothing to validate against until that schema exists and is hosted. Once it's in place, the rest of this section — the core spec, hosting, and how the validator resolves it — follows.

Primary source: Beckn v2 protocol specification, beckn.yaml

Specification URL: beckn.yaml

Use beckn.yaml as the source of truth for v2 actions, schemas, response formats, signing expectations, and validation behavior. Confirm the exact protocol version and supported actions before making any code or ONIX configuration changes.

Schema validation itself is automatic: ONIX's schema2validator plugin validates every payload against both the core protocol schema and any domain-specific extended schema. Teams don't need to write custom validation code — the readiness work is making sure both schemas are correctly in place.

Core protocol vs. domain-specific schema

  • Domain-specific extended schema — Create this first, before any other schema readiness step. It covers domain-specific fields (for example, agri-procurement or soil-testing attributes) that aren't covered by the core schema. A separate extended schema is required for each domain migrating to v2.

  • Core protocol — beckn.yaml, referenced above. Covers actions, context, and structure common to every domain.

  • schema2validator doesn't need the extended schema URL configured manually — it fetches the schema automatically from the @context field carried in the incoming payload's JSON-LD context.

  • Host the extended schema on a raw GitHub URL for testing, and on schema.nfh.global for production. Payloads for each environment must reference the matching URL through @context.

  • Re-host and re-reference the schema whenever the domain schema changes. A stale hosted schema causes schema2validator to pass or fail payloads incorrectly.

What to confirm

  • Target protocol version and action list.

  • Field-level mapping from v1 to v2 for every supported action.

  • Mandatory v2 fields that don't exist in the current v1 payload.

  • Business concepts affected by v2 changes, including catalog, offer, contract, performance, fulfillment, status, payment, and settlement data.

3. ONIX configuration

ONIX is the adapter layer for the v2 migration path and must be configured for every participant. It handles routing, signing, schema validation, and DEDI registry lookup for v2 network communication.

Configuration checklist

  • Correct ONIX version for Beckn v2.

  • Participant role and enabled plugins.

  • Application-facing and network-facing endpoints.

  • Signing keys, verification behavior, and authorization settings.

  • Schema validation for v2 requests and callbacks.

  • DEDI registry lookup and participant discovery.

  • Restart or redeploy process after configuration changes.

Adapter config reference

Each role runs its own adapter config file. Confirm both are present and correctly configured before go-live:

Adapter config
Role
Modules configured

bap-config.yaml

bap

bapTxnReceiver (/bap/receiver/) and bapTxnCaller (/bap/caller/)

bpp-config.yaml

bpp

bppTxnReceiver (/bpp/receiver/) and bppTxnCaller (/bpp/caller/)

4. Business application migration options

Every network participant (NP) is expected to reach full v2 migration — there is no second, equally valid destination. An NP that cannot get there on the required timeline doesn't get to treat that as a stopping point; it needs a documented, time-boxed exception with a plan to close the gap.

Primary path — full v2 migration

The application natively produces and consumes Beckn v2 payloads. Every NP should plan for this outcome by default.

Application responsibilities

  • Update request builders and callback handlers for v2 schemas.

  • Update domain models where v2 concepts differ from v1.

  • Update catalog, contract, performance, fulfillment, status, payment, and settlement logic.

  • Update fixtures, automated tests, and API collections to use v2 payloads.

  • Configure ONIX for v2 network connectivity (see Section 3).

Fallback path — phased migration with reqmapper

Use this path only when an NP does not agree to, or cannot complete, immediate v2 migration — for example, because of a legacy application dependency or a resourcing constraint. While reqmapper is in place, the NP continues to send and receive v1 payloads at the application boundary, and ONIX (configured per Section 3, plus the reqmapper plugin described in the Reqmapper Configuration Reference below) handles v1-to-v2 and v2-to-v1 transformation.

Critically, using reqmapper is conditional: the NP must be actively and visibly migrating its application to full v2 support in parallel. Reqmapper is a bridge for the transition period, not a permanent architecture.

Application responsibilities

  • Keep existing v1 request and callback behavior stable while the mapper is active.

  • Provide complete v1 payload samples for every supported action.

  • Confirm every required business field can be represented in the mapped v2 payload.

  • Test the full flow through ONIX, not only at the application boundary.

  • Run the v2-native migration in parallel, with a tracked plan and milestone dates.

  • Set a firm milestone for removing the mapper dependency and reconfiguring ONIX for v2-only connectivity.

Decision rule

Default to full v2 migration for every NP. Only fall back to reqmapper when an NP cannot migrate on the required timeline, and only with a documented parallel migration plan and a retirement date for the mapper. Reqmapper should never be adopted as a long-term substitute for v2 migration.

Reqmapper Configuration Reference

This section applies only if you are using the reqmapper fallback path described in Section 4. If your application is fully v2-native, you can skip it entirely. It covers the mapper's configuration, components, and general transformation behavior only — it is not specific to any single use case or domain.

Technical overview

The ONIX adapter bridges Beckn protocol v1.x and v2.x networks using a file-based transformation layer called the request mapper. Rather than hard-coding payload shapes in the adapter binary, all transformation logic lives in a single YAML file containing JSONata expressions. The adapter loads this file at startup and applies the right expression automatically based on the action and the participant role (BAP or BPP).

This section explains how the mapper is wired into ONIX, what it transforms, and how transformations are structured for each Beckn action.

How the mapper plugs into ONIX

Configuration

The mapper is declared as a plugin named payloadTransformer in the adapter config (configs/bpp-config.yaml / bap-config.yaml):

role tells the plugin which side of the mapping to apply. mappingsFile is the path to the YAML file mounted into the container.

The transformPayload step

Each module (Receiver and Caller) defines an ordered list of pipeline steps. The transformPayload step is where payload conversion happens:

BAP Receiver (/bap/receiver/) — receives v2 callbacks from the network, converts to v1 for the BAP app:

validateSign → addRoute → validateSchema → transformPayload

BAP Caller (/bap/caller/) — receives v1 requests from the BAP app, converts to v2 for the network:

transformPayload → addRoute → sign → validateSchema

BPP Receiver (/bpp/receiver/) — receives v2 from the network, converts to v1 for the BPP app:

validateSign → addRoute → validateSchema → transformPayload

BPP Caller (/bpp/caller/) — receives v1 from the BPP app, converts to v2 for the network:

transformPayload → addRoute → sign → checkPolicy → validateSchema

The step position determines which payload version the surrounding steps see. On Receiver modules, schema validation runs before transformPayload (validating the incoming v2 payload); on Caller modules, it runs after (validating the outbound v2 payload).

Mapping architecture: bapMappings vs. bppMappings

Each Beckn action in the mappings file has two entries:

Entry
Direction
Applied when

bapMappings

v1 → v2 (outbound) or v2 → v1 (inbound)

adapter running as BAP

bppMappings

v2 → v1 (inbound) or v1 → v2 (outbound)

adapter running as BPP

The role field in the plugin config (bap or bpp) determines which entry is used at runtime. This keeps a single mappings file shared between both roles.

Transformation levels

Transformations happen at two levels in every action:

1. Context level (universal)

Every message, regardless of action, carries a context block. The field names changed between v1 and v2:

v1 field
v2 field
Notes

domain

networkId

Identifies the Beckn network/domain

bap_id

bapId

Consumer platform identifier

bap_uri

bapUri

Consumer platform endpoint

bpp_id

bppId

Provider platform identifier

bpp_uri

bppUri

Provider platform endpoint

transaction_id

transactionId

Correlation ID for a full transaction

message_id

messageId

Unique ID per request

version: "1.0.0"

version: "2.0.0"

Protocol version literal

The mapper always rewrites version and all snake_case → camelCase context fields.

2. Message/payload level (per-action)

Each action also transforms the message body. The substantive schema changes between v1 and v2 — such as renamed structures, restructured catalogs, and coded metadata — happen here. Unlike the context-level rewrite above, message-level field mappings are not generic: they depend on the specific v1 payload shape a given business application sends, and the v2 structure the target network expects, for each action (discover, on_discover, confirm, status, and so on).

Because those payload shapes differ by use case and domain, exact field-level mapping rules are not enumerated here. Each network's mappings file defines its own bapMappings and bppMappings JSONata expressions per action, following the entry structure described above. Treat the per-action mapping logic as something to write and review against your specific v1 and v2 payload samples, not something to copy from a generic reference.

Summary of schema changes (v1 → v2)

The rows below are structural, protocol-level renames that apply regardless of domain. Field-level content within catalogs, orders, and fulfillments varies by use case and is not enumerated here — see the note above.

Category
v1
v2

Context field names

snake_case (bap_id, bpp_uri)

camelCase (bapId, bppUri)

Protocol version

"1.0.0"

"2.0.0"

Domain identifier

context.domain

context.networkId

Catalog items

providers[].items[]

catalogs[].resources[] + catalogs[].offers[]

Order object

message.order

message.contract

Fulfillment status

order.fulfillments[].state

contract.performance[].status

Geo search

Intent-based (flat address)

filters (JSONPath) + spatial (S_DWITHIN)

Adapter configuration

The mapper file path is configured separately in the BAP and BPP adapter configs under payloadTransformer.config.mappingsFile. Both roles (BAP and BPP) share the same mappings file — the role field in the plugin config (bap or bpp) determines which entry (bapMappings or bppMappings) is applied at runtime.

Adapter config
Role
Modules configured

bap-config.yaml

bap

bapTxnReceiver (port 8081, /bap/receiver/) and bapTxnCaller (/bap/caller/)

bpp-config.yaml

bpp

bppTxnReceiver (port 8082, /bpp/receiver/) and bppTxnCaller (/bpp/caller/)

When deploying, the mappings file is mounted into the container and its path is referenced by mappingsFile. No adapter code changes are required when updating the mappings — only a container restart is needed.

Challenges and maintenance considerations

Mapper must be updated for every new field

The JSONata expressions in the mappings file explicitly enumerate every field that needs to be carried across. If a new field is added to a v1 payload (by the BPP or BAP application) and is not handled in the corresponding mapping expression, that field will be silently dropped during transformation. The adapter will not throw an error — it simply produces an output that omits the unrecognized field.

This means:

  • Any new v1 field added to order, items, tags, fulfillments, or context must have a corresponding mapping added to confirm.bapMappings / confirm.bppMappings (and likewise for other actions).

  • Any new v2 field added by the network side must be handled in the reverse direction.

  • The same applies to new entitlementIds codes: if a BPP starts sending a new code in v2, on_discover.bapMappings (and the on_confirm/on_status equivalents) must add a rule to convert it back to the correct v1 tags group. Without this, the tag is either dropped or falls through to the generic "unknown" passthrough handler, where one exists.

No schema-awareness at transform time

The mapper operates on raw JSON; it has no knowledge of the Beckn schema. If the input payload has an unexpected structure (for example, items is an object instead of an array), the JSONata expression may produce an incorrect output silently. Schema validation (the validateSchema step) is the safety net, but it runs separately from the transform and only validates the version it receives.

Bidirectional parity must be maintained

bapMappings and bppMappings for a given action are mirror images of each other. When one is updated, the other typically needs a matching update. Letting them diverge can cause round-trip data loss — for example, a field survives the outbound transform but is missing from the inbound response.

Adding or modifying a mapping

  1. Open the mappings file (path configured in the adapter config under payloadTransformer.config.mappingsFile).

  2. Find the relevant action block (for example, on_discover:).

  3. Edit the bapMappings or bppMappings JSONata expression, and update the mirror direction if the change affects round-trip data.

  4. Redeploy the adapter — no code changes needed, only a container restart.

  5. Verify with the relevant Postman collection covering the affected action.

JSONata expressions have access to the full input payload via $ and support functions like $map, $filter, $merge, $append, $reduce, $string, $number, $boolean, $replace, startswith, and sprintf-style string formatting via the adapter's runtime.

Last updated

Was this helpful?