Operating it
Onboarding a participant
Admitting an identity to a registry: the Participants section's Onboard a participant disclosure in the console, and the signed write behind it. This is the operation that decides who the network will believe, so it is operator-gated and there is no self-service path.
Policy — who should be admitted, and on whose authority — is governance. This page is the mechanics.
What a participant record is for
A record binds a subscriber_id to the public keys that identity signs with,
plus enough metadata for a router to act on it. When an ONIX adapter receives a
signed message it looks up the sender here and verifies the signature against
what it finds. That single lookup is the reason the registry exists.
Which means the failure that matters is not "the record is missing" — that fails loudly and gets fixed. It is the record is present and wrong: a stale key publishes an identity nobody can verify, and it is indistinguishable from that participant being compromised. Getting a key right is more important than getting a record in quickly.
The fields
These are the payload field names ONIX's dediregistry client reads, and the
ones the console writes.
| Field | Notes |
|---|---|
subscriber_id |
The identity as the network names it, e.g. bpp.example.com. |
type |
BAP, BPP, BG or CDS, the enum in the standard's Beckn_subscriber schema. The console offers the first three. |
status |
SUBSCRIBED for a live participant. The Beckn lookup and discovery answer only for SUBSCRIBED or no status at all. |
url |
Where the network reaches them. |
domain |
What they serve, e.g. retail. Feeds discovery. |
network_memberships |
Which networks this binding is valid on. ONIX rejects a sender whose list does not include its own network. |
signing_public_key |
The Ed25519 key signatures are checked against, standard base64. |
encr_public_key |
The X25519 encryption key. |
valid_from / valid_until |
Optional; the binding's own lifetime. A lookup reports expired / not_yet_valid against them, but still answers. |
ttl |
Optional; seconds a client may cache this record. Overrides the node's DEDI_TTL. |
The key id is not a field: it is the record's name.
The record name is the key id, not the subscriber
This trips people up, so it is worth stating plainly: records are named by key id, the id the participant's adapter sends with every signature. ONIX looks a sender up as
GET /dedi/lookup/{subscriber_id}/subscribers.beckn.one/{key_id}
and the node answers it by finding the latest live record named {key_id}
whose payload subscriber_id (or namespace) is {subscriber_id}, in a
namespace allowed to answer it (DEDI_WILDCARD_NAMESPACES). A record named anything else is
never found by that lookup. One subscriber may hold several keys, and each
binding gets its own record so each can be revoked on its own.
Discovery (?domain=), on the other hand, matches on the payload and ignores
the name. So a record mistakenly named after the subscriber sits alongside the
correct one, invisible to signature validation but returned by discovery: the
participant is listed twice, and revoking the key-named record leaves the other
still handed out as a destination. We shipped that bug on the demo network.
The payload must be flat
The Beckn wildcard lookup matches subscriber_id at the top level of the
payload. A record whose fields are nested under details resolves for nobody.
details in the response is a projection the read plane builds. It is not the
shape you publish.
Required by our own schema
countries is required by the standard's Beckn_subscriber schema, which this
node ships as a built-in reference schema. A
registry created with "schema": "builtin:Beckn_subscriber" rejects a record
without it, and the conformance suite's beckn profile checks for it. The
console's form does not ask for it, so add it when you publish into such a
registry. ISO 3166-1 alpha-3.
Doing it from a script
The console is convenient for one participant. For a set you want to be reviewable and repeatable, sign the same request from a shell:
cat > party.json <<JSON
{"payload":{
"subscriber_id":"bpp.example.com",
"url":"https://bpp.example.com/beckn",
"type":"BPP",
"domain":"retail",
"countries":["IND"],
"signing_public_key":"$PUBKEY","encr_public_key":"$PUBKEY",
"status":"SUBSCRIBED",
"network_memberships":["beckn.one/testnet"],
"ttl":300}}
JSON
dedid sign -key publisher.key -kid op-1 \
-method POST \
-path /admin/namespaces/$NS/registries/$REG/records/$KEY_ID/publish \
-body party.json -create > headers.txt
curl -s -u "admin:$DEDI_ADMIN_PASSWORD" -X POST \
"$DEDI/admin/namespaces/$NS/registries/$REG/records/$KEY_ID/publish" \
-H @headers.txt -H 'Content-Type: application/json' --data-binary @party.json
-create says the record must not exist yet; re-publishing one that does needs
-if-match, below.
Never hardcode the public key. Read it from the participant, every run. Ours
were literals in a seeding script; the adapters' keys were rotated; the script
went on publishing keys the signers had stopped using. Every write returned 200,
every record read back looking correct, and the whole network failed one layer
away with 401 Signature Validation Error.
Publishing twice is how you reconcile, not something to avoid
The write is a conditional upsert. Read the record's current version tag and
send it as -if-match; send -create when it does not exist yet:
t=$(curl -s "$DEDI/dedi/lookup/$NS/$REG/$KEY_ID?include_revoked=true" | jq -r '.data.version_tag // empty')
[ -n "$t" ] && pre="-if-match $t" || pre="-create"
That makes re-running a seed the way you bring the registry back in line with the file that describes it, and it makes a concurrent change someone else made fail loudly instead of being silently overwritten.
Verify what landed, not that it was accepted
A 200 means the write was signed correctly and appended. It does not mean the contents are right. Read the record back and check the field that matters:
curl -s "$DEDI/dedi/lookup/$NS/$REG/$KEY_ID" \
| jq '.data.details | {subscriber_id, type, url, signing_public_key}'
Then check it end to end: have the participant sign something and confirm a counterparty verifies it. That is the only test of an onboarding that measures the thing onboarding is for.