Nirmitee.io
ABDMABDM V3Healthcare Interoperability

ABDM V3 API Migration Guide (2026): What Changed from v0.5, Full Endpoint Map and Working Patterns

March 18, 202616 min readUpdated Sep 29, 2026
Written by
Dinesh Thorat
Dinesh Thorat

Digital Growth Lead

Writes about healthcare technology, interoperability, and AI-driven transformation across modern care systems.

ABDM V3 API Migration Guide (2026): What Changed from v0.5, Full Endpoint Map and Working Patterns

Migrating an ABDM integration from v0.5 to V3 means moving every gateway call under /api/hiecm with v3 paths, moving your callback routes under /api/v3, sending the V3 headers (REQUEST-ID, TIMESTAMP, X-CM-ID and X-HIP-ID or X-HIU-ID) on every call, getting sessions from gateway/v3/sessions, and moving Milestone 1 to the V3 ABHA APIs. What does not change is the asynchronous pattern: most callbacks, discovery included, are still acknowledged with HTTP 202 and answered later through an on-* endpoint.

This ABDM V3 API migration guide maps what changed, gives the V3 endpoint list we use in production-grade integrations, shows the patterns for sessions, callbacks, discovery, consent and data transfer, and ends with a migration checklist and a test plan for the sandbox. It is written from building V3 integrations for hospital software and comparing them call by call with an integration NHA has already certified. Updated September 2026.

What changed in ABDM V3, in short

Areav0.5V3
Gateway basehttps://dev.abdm.gov.in/gateway/v0.5/...https://dev.abdm.gov.in/api/hiecm/... (sandbox), https://apis.abdm.gov.in/api/hiecm/... (production)
Session/gateway/v0.5/sessions/api/hiecm/gateway/v3/sessions with grantType: client_credentials
Callbacks to you/v0.5/... paths on your bridge/api/v3/hip/..., /api/v3/hiu/..., /api/v3/consent/... on your bridge
HeadersAuthorization and X-CM-IDAuthorization, REQUEST-ID, TIMESTAMP, X-CM-ID, and X-HIP-ID or X-HIU-ID
CorrelationRequest ID in the bodyBody requestId must equal the REQUEST-ID header on on-* replies
M1 (ABHA)Health ID APIsV3 ABHA APIs on a separate host: abhasbx.abdm.gov.in/abha/api/v3 (sandbox), abha.abdm.gov.in/api/abha/v3 (production)
DiscoveryAsynchronousStill asynchronous: 202, then on-discover

If you would rather have the migration done or reviewed for you, our ABDM integration services team migrates and re-certifies hospital software on V3.

Why V3, and is v0.5 still supported?

V3 is the current ABDM API generation. The official NHA reference implementation, the ABDM wrapper, is built on V3, and new integrations and NHA test cases are written against V3 paths. Treat v0.5 as legacy: plan new work on V3 and migrate existing integrations before you depend on a v0.5 path that may stop answering.

The "discovery is synchronous" myth

Several guides, including an earlier version of this one, describe V3 patient discovery as synchronous, with the patient's care contexts returned in the HTTP response. That is not how the certified integrations we compared against behave. In V3, ABDM calls your /api/v3/hip/patient/care-context/discover route; you answer with HTTP 202 straight away, run the patient match in the background, and send the result to /api/hiecm/user-initiated-linking/v3/patient/care-context/on-discover.

// V3 discover: acknowledge first, answer asynchronously
app.post('/api/v3/hip/patient/care-context/discover', async (req, res) => {
  await queue.add('discover', {
    inboundRequestId: req.headers['request-id'],
    hipId: req.headers['x-hip-id'],
    body: req.body
  });                          // store it
  res.status(202).end();       // ACK now, before any matching
});

// Worker: match the patient, then reply to on-discover
worker.on('discover', async ({ inboundRequestId, hipId, body }) => {
  const match = await findPatient(hipId, body.patient);   // your HMIS lookup
  const replyId = uuid();                                 // body requestId = REQUEST-ID header
  const reply = { requestId: replyId, timestamp: new Date().toISOString(),
                  transactionId: body.transactionId, response: { requestId: inboundRequestId } };
  if (match && match.careContexts.length > 0) {
    reply.patient = [{
      referenceNumber: match.id,
      display: match.name,
      careContexts: match.careContexts.map(c => ({ referenceNumber: c.ref, display: c.display })),
      hiType: 'OPConsultation',
      count: match.careContexts.length
    }];
    reply.matchedBy = ['MR'];                              // MOBILE or MR
  } else if (match) {
    reply.error = { code: 'NOTHING_TO_LINK', message: 'All your records at this facility are already linked.' };
  } else {
    reply.error = { code: 1000, message: 'No matching patient found' };
  }
  await gateway.post('/user-initiated-linking/v3/patient/care-context/on-discover', reply,
                     { requestId: replyId, hipId });
});

Three details from the certified behavior we follow: send matchedBy as MOBILE or MR, because the sandbox PHR app rejects other values; answer a patient who is not found with error code 1000 rather than staying silent; and when the patient matches but every record is already linked, send a message that says so, because an empty list makes the PHR app report a failure. Match on your own patient ID where the request carries it; it avoids ABDM's duplicate discovery errors.

V3 sessions and the headers every call needs

const HIECM = process.env.ABDM_ENV === 'production'
  ? 'https://apis.abdm.gov.in/api/hiecm'
  : 'https://dev.abdm.gov.in/api/hiecm';

let token = null, expiresAt = 0;
async function session() {
  if (token && Date.now() < expiresAt - 60_000) return token;
  const res = await axios.post(`${HIECM}/gateway/v3/sessions`,
    { clientId: process.env.ABDM_CLIENT_ID, clientSecret: process.env.ABDM_CLIENT_SECRET, grantType: 'client_credentials' },
    { headers: { 'Content-Type': 'application/json', 'REQUEST-ID': uuid(), 'TIMESTAMP': new Date().toISOString(), 'X-CM-ID': 'sbx' } });
  token = res.data.accessToken;
  expiresAt = Date.now() + res.data.expiresIn * 1000;  // use expiresIn from the response
  return token;
}

function headers(requestId, facility) {
  return {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${facility.token}`,
    'REQUEST-ID': requestId,              // same value as body.requestId where the body has one
    'TIMESTAMP': new Date().toISOString(),
    'X-CM-ID': facility.cmId,             // "sbx" in the sandbox
    ...(facility.hipId ? { 'X-HIP-ID': facility.hipId } : {}),
    ...(facility.hiuId ? { 'X-HIU-ID': facility.hiuId } : {})
  };
}
  • REQUEST-ID must match. On every on-* reply, the body's requestId and the REQUEST-ID header carry the same value. A mismatch is one of the quietest V3 failures.
  • X-HIP-ID for HIP calls, X-HIU-ID for HIU calls. Sending the HIP header on an HIU consent request is a common NHA test failure.
  • Refresh from expiresIn. Do not hard-code a token lifetime.

Bridge URL and routing callbacks in V3

The bridge URL is set once per client ID with PATCH /api/hiecm/gateway/v3/bridge/url, and you can read what is registered with GET /api/hiecm/gateway/v3/bridge-services. Every callback for every facility under that client ID arrives at the same base URL; route by path and by the X-HIP-ID or X-HIU-ID header.

Three rules decide whether callbacks work in V3: answer every callback with 202 immediately and do the work in a background worker; never drop an unknown callback silently; and keep your tunnel or ingress healthy, because ABDM does not resend a lost consent notification. More debugging patterns are in our bridge URL and callback debugging guide.

ABDM V3 endpoint reference

These are the V3 paths as used in the integrations we build, checked against a certified reference. Gateway paths are relative to the HIECM base; callback paths are on your bridge URL.

You call the gateway (HIECM base)

PurposeV3 path
Session tokenPOST /gateway/v3/sessions
Register or read the bridge URLPATCH /gateway/v3/bridge/url, GET /gateway/v3/bridge-services
Public certificatesGET /gateway/v3/certs
HIP link token for a patientPOST /v3/token/generate-token
Link care contextsPOST /hip/v3/link/carecontext
SMS the patient about a new recordPOST /hip/v3/link/patient/links/sms/notify2
Answer discoveryPOST /user-initiated-linking/v3/patient/care-context/on-discover
Answer link init and confirmPOST /user-initiated-linking/v3/link/care-context/on-init, .../on-confirm
Acknowledge a consent (HIP)POST /consent/v3/request/hip/on-notify
Acknowledge a data request (HIP)POST /data-flow/v3/health-information/hip/on-request
Report a finished transferPOST /data-flow/v3/health-information/notify
Answer Scan and SharePOST /patient-share/v3/on-share
Request consent (HIU)POST /consent/v3/request/init, POST /consent/v3/request/status
Acknowledge consent and fetch the artefact (HIU)POST /consent/v3/request/hiu/on-notify, POST /consent/v3/fetch
Request health data (HIU)POST /data-flow/v3/health-information/request

ABDM calls you (bridge URL)

CallbackV3 route on your bridge
Link token result/api/v3/hip/token/on-generate-token
Patient discovery/api/v3/hip/patient/care-context/discover
Link init and confirm/api/v3/hip/link/care-context/init, /api/v3/hip/link/care-context/confirm
Consent granted or revoked (HIP)/api/v3/consent/request/hip/notify
Health data request (HIP)/api/v3/hip/health-information/request
Scan and Share profile/api/v3/hip/patient/share
ABHA deactivation or opt-out/api/v3/hip/patient/abha/deactivate
Consent request acknowledged (HIU)/api/v3/hiu/consent/request/on-init
Consent granted, denied, revoked or expired (HIU)/api/v3/hiu/consent/request/notify
Consent artefact (HIU)/api/v3/hiu/consent/on-fetch
Data request acknowledged (HIU)/api/v3/hiu/health-information/on-request
Encrypted data push (HIU)the dataPushUrl you sent, for example /api/v3/hiu/health-information/push

The complete, callable set with sandbox and production variables is in our public ABDM V3 Postman collection.

Consent and data transfer in V3

The consent and data flow keep their shape in V3; the paths and headers are what change.

  • HIP side. On /api/v3/consent/request/hip/notify, store the consent and acknowledge with consent/v3/request/hip/on-notify. On /api/v3/hip/health-information/request, acknowledge with hip/on-request, build the FHIR bundles for the consented care contexts, encrypt each with Fidelius using fresh HIP key material, push them to the requester's dataPushUrl with an MD5 checksum of the encrypted content, then report the result with data-flow/v3/health-information/notify.
  • HIU side. Raise the consent with consent/v3/request/init and X-HIU-ID, acknowledge the grant, fetch the artefact, request the data with your Fidelius public key and data push URL, decrypt what arrives, and delete the records and keys when the consent is revoked or expires. Our HIU reference architecture covers storage and purge.

The V3 consent request body (HIU)

{
  "requestId": "0b7e0f1a-4c2d-4f5e-9a1b-2c3d4e5f6a7b",
  "timestamp": "2026-09-28T05:00:00.000Z",
  "consent": {
    "purpose": { "text": "Care Management", "code": "CAREMGT", "refUri": "http://terminology.hl7.org/ValueSet/v3-PurposeOfUse" },
    "patient": { "id": "patient@sbx" },
    "hiu": { "id": "YOUR-HIU-ID" },
    "hip": { "id": "HIP-ID-IF-YOU-WANT-ONE-HOSPITAL" },
    "requester": { "name": "Dr. Test Doctor", "identifier": { "type": "REGNO", "value": "REG-NUMBER", "system": "REGISTRY-SYSTEM-URL" } },
    "hiTypes": ["OPConsultation", "DiagnosticReport", "Prescription"],
    "permission": {
      "accessMode": "VIEW",
      "dateRange": { "from": "2025-01-01T00:00:00.000Z", "to": "2026-09-28T00:00:00.000Z" },
      "dataEraseAt": "2026-10-28T00:00:00.000Z",
      "frequency": { "unit": "HOUR", "value": 1, "repeats": 0 }
    }
  }
}
  • To ask every provider that holds the patient's records, leave the hip key out entirely. Sending "hip": null is rejected.
  • When you later request the data, copy the granted dateRange from the fetched consent artefact exactly as returned; a reformatted date range fails with ABDM-1063.

The V3 data push body (HIP to HIU)

{
  "pageNumber": 0,
  "pageCount": 1,
  "transactionId": "transaction-id-from-the-request",
  "entries": [{
    "content": "BASE64-ENCRYPTED-FHIR-BUNDLE",
    "media": "application/fhir+json",
    "checksum": "MD5-OF-THE-ENCRYPTED-CONTENT",
    "careContextReference": "OPD-2026-09-28-001"
  }],
  "keyMaterial": {
    "cryptoAlg": "ECDH",
    "curve": "Curve25519",
    "dhPublicKey": { "expiry": "2026-09-29T05:00:00.000Z", "parameters": "Curve25519/32byte random key", "keyValue": "HIP-PUBLIC-KEY" },
    "nonce": "HIP-NONCE"
  }
}

Large transfers are split into pages. We generate a fresh HIP key pair and nonce for every page and never reuse them across pages; the receiver needs the key material in each page to decrypt that page's entries. After the last page, the HIP reports the transfer with data-flow/v3/health-information/notify, and the HIU reports what it received, per care context, with its own notify.

Scan and Share in V3: what the QR carries

A facility's Scan and Share QR identifies the facility's HIP ID and a counter code; decoded, it can appear as a small object such as {"hipId":"IN0000000000","code":"1"}, where code identifies the registration counter. When a patient scans it, ABDM calls your /api/v3/hip/patient/share route with the patient's profile; you register or match the patient and answer patient-share/v3/on-share with a token number for the queue. Use a different counter code for each registration counter so you know where the patient is standing.

"ABDM gateway not responding": what to check first in V3

  • Network blocks. ABDM's hosts sit behind a web application firewall. Some developer networks and VPN exits are refused with 403 before your request reaches the API; test from the server that will run the integration.
  • The wrong base or version. A v0.5 path on the V3 base, or the sandbox base with production credentials, fails in confusing ways.
  • Missing headers. A missing TIMESTAMP, X-CM-ID or X-HIP-ID is refused even when the token is valid.
  • Callbacks that never arrive. Check the registered bridge URL with bridge-services; after a change, allow time before callbacks move, and make sure the tunnel or ingress is alive.

Specific error codes and fixes are in our 25 common ABDM errors guide and the public ABDM V3 error catalog.

ABDM v0.5 to V3 migration checklist

  1. Inventory every v0.5 call you make and every callback you handle.
  2. Map each one to its V3 path; set the sandbox and production HIECM and ABHA bases as configuration.
  3. Switch sessions to gateway/v3/sessions and add the V3 headers to every call.
  4. Move callback routes under /api/v3, keep answering 202 first, and re-register the bridge URL.
  5. Make every on-* reply carry the same request ID in body and header.
  6. Move M1 to the V3 ABHA enrolment and two-step login APIs.
  7. Run NHA's test cases for every milestone in the sandbox, fix, and run them again.
  8. Cut over in production and watch callback and error logs closely for the first week.

How to test your ABDM V3 integration in the sandbox

  1. Expose your server on a public HTTPS URL and register it as the bridge URL.
  2. Check registration with bridge-services before testing callbacks.
  3. Test discovery and linking from a PHR app with a sandbox ABHA, and confirm on-discover, on-init and on-confirm are accepted.
  4. Test consent and data transfer end to end, including revoke, and check the receiving side can decrypt every record.
  5. Log every exchange with its REQUEST-ID so any failure can be traced and reported to sandbox support.

In our own V3 testing in September 2026, a full M3 run against the sandbox delivered every value in every test record intact: 526 of 526 values and 30 of 30 attachments. The full integration path, from sandbox registration to go-live, is in our ABDM integration step-by-step guide, and what each milestone covers is in the ABDM milestones guide.

Migrating to ABDM V3 or starting fresh? Our ABDM integration team migrates, tests and re-certifies hospital software on V3. Talk to our team for a review of your integration.

Ready to scale?

Talk to our healthcare engineering team about building, integrating, and shipping faster.

Frequently Asked Questions

Is ABDM v0.5 still supported?

Treat v0.5 as legacy. The official NHA ABDM wrapper and current NHA test cases use V3 paths, so new integrations should be built on V3 and existing ones migrated before they depend on a v0.5 path that stops answering.

What is the biggest change in ABDM V3?

The paths and headers. Gateway calls move under /api/hiecm with v3 paths, your callback routes move under /api/v3, and every call carries REQUEST-ID, TIMESTAMP, X-CM-ID and X-HIP-ID or X-HIU-ID, with the body requestId matching the REQUEST-ID header on on-* replies.

Is ABDM V3 discovery synchronous?

No. ABDM calls your /api/v3/hip/patient/care-context/discover route, you answer HTTP 202 immediately, and you send the result to user-initiated-linking/v3/patient/care-context/on-discover. Certified integrations follow this asynchronous pattern.

What is hiecm in ABDM?

HIECM is the base path of the ABDM V3 gateway APIs: https://dev.abdm.gov.in/api/hiecm in the sandbox and https://apis.abdm.gov.in/api/hiecm in production. Sessions, bridge URL, linking, consent and data-flow calls all sit under it.

How do I get an ABDM V3 session token?

POST clientId, clientSecret and grantType client_credentials to /api/hiecm/gateway/v3/sessions with REQUEST-ID, TIMESTAMP and X-CM-ID headers. Use the accessToken in the Authorization header and refresh it from the expiresIn value in the response.

Can I run v0.5 and V3 side by side during migration?

Only with care. The bridge URL is set per client ID, so one environment receives the callbacks. Migrate in the sandbox first, run NHA's test cases on V3, then cut production over in one planned step.

Why is the ABDM gateway not responding to my V3 calls?

The usual causes are a network or VPN exit refused by ABDM's firewall with 403, a v0.5 path used on the V3 base, missing V3 headers, or a bridge URL that is not registered or not reachable for callbacks. Check each from the server that will run the integration.

Where can I find the full list of ABDM V3 endpoints?

This guide lists the V3 paths for sessions, bridge URL, linking, consent and data flow. Nirmitee's public ABDM V3 Postman collection has the full callable set with sandbox and production variables.
Share