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:
Namespace creation — Create and verify the participant's namespace by proving domain ownership. This establishes the root of trust for everything published under it.
Registry publication — Add a registry under that namespace, following the NFH fabric subscriber schema, to list Beckn subscriber details.
Subscriber record creation — Publish subscriber records for each participant, including callback URL, network role (consumer/provider node, etc.), domain code, and public key.
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
If your organization is a Network Participant (NP) registering subscriber details on an existing network, follow Network Participants registering on the NFH fabric.
If your organization is instead a Network Facilitator Organization (NFO) setting up a new network, follow Setting up the network environment.
For background on the service itself, see the REGISTR product overview.
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.schema2validatordoesn't need the extended schema URL configured manually — it fetches the schema automatically from the@contextfield 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
schema2validatorto 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:
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:
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:
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.
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.
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, orcontextmust have a corresponding mapping added toconfirm.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
entitlementIdscodes: if a BPP starts sending a new code in v2,on_discover.bapMappings(and theon_confirm/on_statusequivalents) must add a rule to convert it back to the correct v1tagsgroup. 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
Open the mappings file (path configured in the adapter config under
payloadTransformer.config.mappingsFile).Find the relevant action block (for example,
on_discover:).Edit the
bapMappingsorbppMappingsJSONata expression, and update the mirror direction if the change affects round-trip data.Redeploy the adapter — no code changes needed, only a container restart.
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?