Quickstart
This guide takes you from zero to a successfully published catalog in a few minutes.
This guide takes you from zero to a successfully published catalog in a few minutes. By the end, you will have submitted a real catalog to CATALG, received an ACK, and received the per-catalog processing result on your callback endpoint.
If you have not yet read what CATALG does, start with the Overview.
Before you start
Two prerequisites must be in place. Both are one-time setup steps for your organisation.
1. A target network must exist in the DeDi registry
Any network you list in publishDirectives[].visibleTo must be registered. If you omit visibleTo, your catalog is distributed via the default global network nfh.global/beckn-nodes — no other network setup is needed. Networks are created and managed by a Network Facilitator. See Build Trusted Networks using REGISTR.
2. Your organisation must be onboarded as a network participant
Your participant identity, Ed25519 signing key, and callback base URL must be registered in the DeDi registry for your target network. Two things depend on this registration:
the Beckn HTTP Signature on your publish request cannot be verified without your registered public key
CATALG resolves your
/catalog/on_publishcallback URL by looking up the registered callback base URL — not by trusting thebppUriin the request body
The registered callback base URL must be a publicly reachable HTTPS endpoint. See Onboarding Network Participants.
Step 1 — Prepare a minimal catalog
A catalog is the JSON payload you submit. Below is a small valid catalog — one provider, one resource, and one offer that references the resource.
{ "context": { "version": "2.0.0", "action": "catalog/publish", "messageId": "f01e0a8a-1111-4111-8111-111111111111", "transactionId": "f01e0a8a-2222-4222-8222-222222222222", "timestamp": "2026-06-02T10:00:00.000Z", "bppId": "bpp.freshmart.local-retail.net", "bppUri": "https://bpp.freshmart.local-retail.net/beckn/" }, "message": { "publishDirectives": [ { "catalogId": "CAT-FRESHMART-HELLO", "catalogType": "REGULAR" } ], "catalogs": [ { "id": "CAT-FRESHMART-HELLO", "descriptor": { "name": "FreshMart Hello Catalog", "shortDesc": "First catalog from FreshMart" }, "provider": { "id": "freshmart-blr-001", "descriptor": { "name": "FreshMart Koramangala" } }, "resources": [ { "id": "ITEM-BASMATI-1KG", "descriptor": { "name": "India Gate Basmati Rice 1KG" }, "resourceAttributes": { "@context": "https://schema.beckn.io/RetailResource/2.1/context.jsonld", "@type": "RetailResource", "brand": "India Gate" } } ], "offers": [ { "id": "OFFER-BASMATI-HELLO", "descriptor": { "name": "Basmati 1KG — Launch Offer" }, "resourceIds": ["ITEM-BASMATI-1KG"], "offerAttributes": { "@context": "https://schema.beckn.io/RetailOffer/2.1/context.jsonld", "@type": "RetailOffer", "isActive": true } } ] } ] } }
A few things to note:
context.bppIdandcontext.bppUriidentify you —bppUriis informational; CATALG resolves the actual callback URL from your DeDi registry entry (see Step 5)publishDirectivesis an array at the message level (not inside the catalog) and is keyed to each catalog bycatalogId. UsepublishDirectives[].visibleToto scope distribution to specific networks; when omitted, the catalog is distributed via the default global networknfh.global/beckn-nodesresources[].resourceAttributesuses a JSON-LD@contextto declare which domain schema the resource followsoffers[].resourceIdslinks the offer to one or more resources by theirid;offers[].offerAttributesdeclares the offer schema (RetailOffer here) the same way resources do
Step 2 — Sign the request
Every publish request must carry a Beckn HTTP Signature in the Authorization header. The signature proves you hold the Ed25519 private key whose corresponding public key is registered against your participant record in the DeDi registry.
You sign and publish the request yourself — the signing flow uses your Ed25519 private key and produces a single-line header value of the form:
Authorization: Signature keyId="{subscriberId}|{recordId}|{algorithm}",algorithm="ed25519",created="{unix_timestamp}",expires="{unix_timestamp}",headers="(created) (expires) digest",signature="{base64-ed25519-signature}"
For the full structure of the header, the keyId format, and what gets signed, see API Reference → Authentication.
Step 3 — POST the catalog
Send the signed request to the CATALG endpoint of the network you are publishing to:
curl -X POST https://catalg.example.net/catalog/publish \ -H "Content-Type: application/json" \ -H "Authorization: Signature keyId=\"...\",algorithm=\"ed25519\",..." \ -d @catalog.json
Step 4 — Inspect the synchronous ACK
If the request is well-formed and your signature verifies, CATALG returns a 200 OK with an ACK:
{ "message": { "status": "ACK", "messageId": "f01e0a8a-1111-4111-8111-111111111111" } }
The messageId is echoed from your request context.messageId. The ACK means CATALG has accepted the request for processing — not that the catalog has been validated against the domain schema yet. That result arrives on the callback in the next step.
If the request is malformed, the signature fails, or you do not own the catalogId, CATALG returns a NACK with an error block in the same envelope. See API Reference → Errors for the full list.
Step 5 — Receive the on_publish callback
CATALG does not trust the bppUri carried in the request body for callback delivery. Instead, it looks up your participant record in the DeDi registry using the identity from your Authorization signature (the keyId), reads the url field from your registered entry, and appends /catalog/on_publish to it. That is the URL it POSTs to.
A registered participant entry looks like this — the url field is what CATALG uses:
{ "subscriber_id": "bpp.freshmart.local-retail.net", "type": "BPP", "url": "https://bpp.freshmart.local-retail.net/beckn/", "domain": "*", "countries": ["IND"] }
Given that entry, CATALG resolves the callback URL as:
registry.url + catalog/on_publish → https://bpp.freshmart.local-retail.net/beckn/catalog/on_publish
The /beckn/ segment is the conventional base path for Fabric-protocol endpoints on a participant's domain — catalog/on_publish is appended onto it.
The url field must therefore be a publicly reachable HTTPS endpoint and must be set correctly in DeDi during onboarding (see Onboarding Network Participants). The bppUri in your request body is informational only — the registry is the source of truth.
Once CATALG finishes processing your catalog, it POSTs the per-catalog result to that resolved URL:
{ "context": { "version": "2.0.0", "action": "catalog/on_publish", "messageId": "f01e0a8a-1111-4111-8111-111111111111", "transactionId": "f01e0a8a-2222-4222-8222-222222222222", "timestamp": "2026-06-02T10:00:02.000Z", "requestDigest": { "digest": "BLAKE-512=mB2c5x...base64..." } }, "message": { "results": [ { "catalogId": "CAT-FRESHMART-HELLO", "status": "ACCEPTED", "stats": { "itemCount": 1, "providerCount": 1, "categoryCount": 1 } } ] } }
The status field on each result is one of:
Status | Meaning |
|---|---|
ACCEPTED | Catalog processed and distributed to all matching subscribers |
REJECTED | Catalog rejected entirely — errors array explains what failed |
PARTIAL | Some resources accepted, some rejected — see errors array |
When status is REJECTED or PARTIAL, each result carries an errors array describing what failed:
{ "results": [ { "catalogId": "CAT-FRESHMART-HELLO", "status": "REJECTED", "errors": [ { "code": "SCHEMA_VALIDATION_FAILED", "message": "message.catalogs[0].resources[0].resourceAttributes.@context is required" } ] } ] }
What just happened?
You sent a single POST /catalog/publish request. CATALG verified your signature, validated the structure against the Fabric v2.0 schema, verified that you own the catalogId, processed the catalog, and stored it as the source of truth for the network. It then asynchronously delivered the result to the callback URL resolved from your DeDi registry entry, and pushed the catalog out to every Discovery Service whose subscription filters matched.
A consumer application can now find your catalog by querying any Discovery Service that subscribed to your network — without that Discovery Service ever calling you directly.
Where to go next
Goal | Page |
|---|---|
Understand the catalog model — resources, offers, master templates, update modes, ownership | |
Receive catalogs as a Discovery Service | |
Look up an endpoint, field, or error code |